<?php

namespace App\V3\V3_2_7\Services;

use App\V3\V3_2_7\Models\AdminModel;
use App\V3\V3_2_7\Models\LogInStorageModel;
use App\V3\V3_2_7\Models\LogOutStorageModel;
use App\V3\V3_2_7\Models\MaterielContentModel;
use App\V3\V3_2_7\Models\MaterielModel;
use App\V3\V3_2_7\Models\MaterielOtherChargesModel;
use App\V3\V3_2_7\Models\MaterielsTypeModel;
use App\V3\V3_2_7\Models\MessBoardModel;
use App\V3\V3_2_7\Models\OperMainAccountModel;
use App\V3\V3_2_7\Models\SellMaterielPrepareOutLogModel;
use App\V3\V3_2_7\Models\StorageBatchModel;
use App\V3\V3_2_7\Models\StorageManageModel;
use App\V3\V3_2_7\Models\StorageModel;
use App\V3\V3_2_7\Models\StorageShelfLocationModel;
use App\V3\V3_2_7\Models\StorageShelfModel;
use App\V3\V3_2_7\Models\SupplierCustomerModel;
use App\V3\V3_2_7\Models\CheckModel;
use App\V3\V3_2_7\Models\MaterielPayHistoryModel;
use App\V3\V3_2_7\Models\TallyClassModel;
use App\V3\V3_2_7\Models\TallyModel;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\V3\V3_2_7\Models\MaterielSerialNumberModel;
use App\V3\V3_2_7\Models\SerialNumberModel;
use App\Services\CommonService;
use App\V3\V3_2_7\Models\MaterielClassModel;
use Illuminate\Support\Carbon;
use App\V3\V3_2_7\Models\MaterielLogisticsInfoModel;
use App\V3\V3_2_7\Models\MaterielTypeModel;
use App\Services\MessageService;

class MaterielService
{
    static public function edit($data, $isUseShelf = 0, $isShareShelfLocation)
    {
        $materielContent = json_decode($data['materiel_content'], true);
        unset($data['materiel_content']);

        $data['purchase_time'] = empty($data['purchase_time']) ? time() : strtotime($data['purchase_time']);

        $newMaterielTypeId = [];//新采购单内容物料id
        $data['original_money'] = 0;//税前应付应付金额
        foreach ($materielContent as $value) {
            $newMaterielTypeId[] = $value['id'];

            $data['original_money'] += $value['num'] * $value['unit_price'];
        }
        //应付金额(税后)
        $data['real_money'] = $data['tax_rate'] == 0 ? $data['original_money'] : $data['original_money'] * ($data['tax_rate'] / 100) + $data['original_money'];
        /**
         * @preferential_way:优惠方式;0:无;1:修改价格;2:折扣优惠;
         * 优惠方式为非0值时，实付金额为修改后的金额或折扣优惠后的金额
         */
        switch ($data['preferential_way']) {
            case 0:
                $data['final_money'] = $data['real_money'];
                break;
            case 1:
                $data['final_money'] = $data['preferential_money'];
                break;
            case 2:
                if ($data['preferential_money'] >= 100) {
                    return ['code' => 1, 'msg' => '折扣比例不能超出百分百', 'data' => ''];
                }
                //折扣后
                $afterDiscount = ($data['original_money'] * ($data['preferential_money'] / 100));
                //税后
                $afterTaxRate = $afterDiscount + ($afterDiscount * ($data['tax_rate'] / 100));
                $data['final_money'] = ceil($afterTaxRate * 100) / 100;//物料均价
                $data['discount'] = $data['preferential_money'];
                break;
        }

        unset($data['preferential_money']);

        $materielContentInfo = MaterielContentModel::where([
            'materiel_id' => $data['id']
        ])->get()->toArray();

        $uselessContentId = [];//修改后无用的采购内容id
        $needsToUpdate = [];
        $existMaterielContentTypeId = [];
        foreach ($materielContentInfo as $kk => $val) {
            //已有采购内容发生替换
            if (!in_array($val['id'], $newMaterielTypeId)) {
                $uselessContentId[] = $val['id'];
            } else {
                $existMaterielContentTypeId[] = $val['id'];
                $v['purchase_time'] = $data['purchase_time'];

                foreach ($materielContent as $k3 => $v3) {
                    if ($val['id'] == $v3['id']) {
                        //仓库信息
                        $storageInfo = StorageModel::where([
                            'id' => $v3['storage_id'],
                            'main_id' => $data['main_id'],
                            'delete_flag' => 0,
                        ])->first();
                        if (empty($storageInfo)) {
                            return ['code' => 1, 'msg' => '仓库`' . $v3['storage_name'] . '`不存在', 'data' => ''];
                        }
                        if (empty($v3['shelf_id']) || empty($v3['location_id'])) {
                            if (!empty($isShareShelfLocation)) {
                                return ['code' => 1, 'msg' => '您开启强制选择货架及库位，请选择！', 'data' => ''];
                            }
                            $shelfId = 0;
                            $locationId = 0;
                            $sfData = ShelfService::get_default($v3['storage_id']);
                            if (!empty($sfData)) {
                                $v3['shelf_id'] = $sfData['id'];
                                $lData = ShelfService::get_default($sfData['id'], 2);
                                $v3['location_id'] = $lData['id'];
                            }
                        }
                        $v3['storage_id'] = $storageInfo['id'];
                        $v3['storage_name'] = $storageInfo['storage_name'];
                        $v3['storage_address'] = $storageInfo['storage_address'];
                        $v3['id'] = $val['id'];
                        $v3['materiel_id'] = $data['id'];
                        $v3['user_id'] = $data['user_id'];
                        $v3['remark'] = !empty($v3['remark']) ? $v3['remark'] : "";
                        $v3['main_id'] = $data['main_id'];
                        $v3['created_at'] = time();
                        $v3['rest_num'] = $v3['num'];
                        $v3['purchase_time'] = !empty($data['purchase_time']) ? $data['purchase_time'] : "";
                        if (!empty($data['is_auto_out_storage'])) {
                            $v3['rest_num'] = 0;
                        }
                        $needsToUpdate[$k3] = $v3;
                    }
                }
            }
        }

        $needsToInsert = [];
        foreach ($materielContent as $k => $v) {
            if (!in_array($v['id'], $existMaterielContentTypeId)) {
                //仓库信息
                $storageInfo = StorageModel::where([
                    'id' => $v['storage_id'],
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0,
                ])->first();
                if (empty($storageInfo)) {
                    return ['code' => 1, 'msg' => '仓库`' . $v['storage_name'] . '`不存在', 'data' => ''];
                }
                if (empty($v['shelf_id']) || empty($v['location_id'])) {
                    $shelfId = 0;
                    $locationId = 0;
                    $sfData = ShelfService::get_default($v['storage_id']);
                    if (!empty($sfData)) {
                        $v['shelf_id'] = $sfData['id'];
                        $lData = ShelfService::get_default($sfData['id'], 2);
                        $v['location_id'] = $lData['id'];
                    }
                }
                $v['storage_id'] = $storageInfo['id'];
                $v['storage_name'] = $storageInfo['storage_name'];
                $v['storage_address'] = $storageInfo['storage_address'];
                $v['materiel_id'] = $data['id'];
                $v['user_id'] = $data['user_id'];
                $v['main_id'] = $data['main_id'];
                $v['created_at'] = time();
                $v['rest_num'] = $v['num'];
                $v['purchase_time'] = $data['purchase_time'];
                if (!empty($data['is_auto_out_storage'])) {
                    $v['rest_num'] = 0;
                }
                unset($v['id']);
                $needsToInsert[] = $v;
            }
        }
        $inStorageArr = $needsToUpdate;
        if (!empty($needsToUpdate) && !empty($needsToInsert)) {
            $inStorageArr = array_merge($needsToUpdate, $needsToInsert);
        } elseif (empty($needsToUpdate) && !empty($needsToInsert)) {
            $inStorageArr = $needsToInsert;
        }
        $supplierInfo = SupplierCustomerModel::where([
            'id' => $data['supplier_customer_id'],
            'main_id' => $data['main_id'],
            'delete_flag' => 0
        ])->first();
        if (empty($supplierInfo)) {
            return ['code' => 1, 'msg' => '供应商，没有找到！', 'data' => ''];
        }
        $data['supplier_customer_id'] = $supplierInfo['id'];
        $data['deliver_person'] = empty($data['deliver_person']) ? $supplierInfo['name'] : $data['deliver_person'];
        $data['deliver_phone'] = empty($data['deliver_phone']) ? $supplierInfo['phone'] : $data['deliver_phone'];
        $data['deliver_address'] = empty($data['deliver_address']) ? $supplierInfo['address'] : $data['deliver_address'];
        $data['supplier_name'] = $supplierInfo['name'];

        $materielInfo = MaterielModel::where('id', $data['id'])->first();
        if (!empty($materielInfo['delete_flag'])) {
            return ['code' => 1, 'msg' => '采购单已删除！', 'data' => ''];
        }
        if (!empty($materielInfo['in_storage_status'])) {
            return ['code' => 1, 'msg' => '采购单已入库，不能修改！', 'data' => ''];
        }
        if ($materielInfo['pay_status'] != 0) {
            unset($data['fact_money']);
        }
        $logInData = [];
        $InlogReg = '';
        DB::beginTransaction();
        try {
            //自动出库处理的逻辑
            if (!empty($data['is_auto_out_storage'])) {
                if (!empty($inStorageArr)) {
                    foreach ($inStorageArr as $iVal) {
                        $goodsInfo = MaterielsTypeModel::where([
                            'id' => $iVal['type_id'],
                            'delete_flag' => 0,
                            'main_id' => $data['main_id']
                        ])->first();
                        if (empty($goodsInfo)) {
                            throw new Exception('商品:' . $iVal['materiel_name'] . '，没有找到！');
                        }
                        $goodsClassInfo = MaterielClassModel::select(
                            'id',
                            'class_name',
                            'class_no',
                            'parent_id'
                        )->where([
                            'id' => $goodsInfo['materiel_class_id'],
                            'delete_flag' => 0
                        ])->first();
                        if (empty($goodsClassInfo)) {
                            throw new Exception('商品:' . $v['materiel_name'] . '的分类，没有找到！');
                        }
                        if (!empty($goodsInfo['is_use_serial']) && !empty($data['is_auto_out_storage'])) {
                            throw new Exception('商品:' . $goodsInfo['materiel_name'] . '已开启了序列号，不能开启自动出库');
                        }

                        //物料当前库存信息
                        if ($isUseShelf) {
                            $storageManageInfo = StorageManageModel::where([
                                'type_id' => $goodsInfo['id'],
                                'storage_id' => $iVal['storage_id'],
                                'main_id' => $iVal['main_id'],
                                'delete_flag' => 0,
                                'shelf_id' => $iVal['shelf_id'],
                                'location_id' => $iVal['location_id']
                            ])->first();
                        } else {
                            $storageManageInfo = StorageManageModel::where([
                                'type_id' => $goodsInfo['id'],
                                'storage_id' => $iVal['id'],
                                'main_id' => $iVal['main_id'],
                                'delete_flag' => 0
                            ])->first();
                        }
                        $newManageId = $storageManageInfo['id'] ?? 0;
                        //检查库存中是否存在该物料
                        if (!empty($storageManageInfo)) {//存在
                            $meanPirce = sprintf("%.6f", (
                                    ($storageManageInfo['materiel_mean_cost'] * $storageManageInfo['in_storage_num'])
                                    + ($v['num'] * $iVal['unit_price']))
                                / ($storageManageInfo['in_storage_num'] + $iVal['num']));

                            StorageManageModel::where([
                                'id' => $storageManageInfo['id']
                            ])->update([
                                'in_storage_num' => $storageManageInfo['in_storage_num'] + $iVal['num'],
                                //'virtual_storage_num' => $storageManageInfo['virtual_storage_num'] + $iVal['num'],
                                'materiel_mean_cost' => $meanPirce
                            ]);
                        } else {//不存在
                            $meanPirce = 0;
                            $num = $v['num'] ?? 0;
                            if ($goodsInfo['cost'] != 0) {
                                $meanPirce = sprintf("%.6f", (
                                        ($goodsInfo['cost'] * $iVal['num']) +
                                        ($iVal['num'] * $iVal['unit_price'])) / $num);
                            } else {
                                $meanPirce = $iVal['unit_price'];
                            }
                            $newManageId = StorageManageModel::insertGetId([
                                'materiel_class_id' => $goodsClassInfo['id'],
                                'materiel_class_name' => $goodsClassInfo['class_name'],
                                'materiel_class_no' => $goodsClassInfo['class_no'],
                                'type_id' => $goodsInfo['id'],
                                'materiel_name' => $goodsInfo['materiel_name'],
                                'type_name' => $goodsInfo['type_name'],
                                'materiel_no' => $goodsInfo['materiel_no'],
                                'materiel_mean_cost' => $meanPirce,
                                'storage_id' => $iVal['storage_id'],
                                'storage_name' => $iVal['storage_name'],
                                'storage_address' => $iVal['storage_address'],
                                'in_storage_num' => $iVal['num'],
                                //'virtual_storage_num' =>  $iVal['num'],
                                'main_id' => $iVal['main_id'],
                                'shelf_id' => $iVal['shelf_id'],
                                'location_id' => $iVal['location_id'],
                                'is_product_materiel' => $goodsInfo['is_product_materiel'],
                                'in_storage_time' => $data['purchase_time'],
                                'created_at' => time()
                            ]);
                        }
                        do {
                            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                        } while (
                            !empty(StorageBatchModel::where('main_id', $data['main_id'])
                                ->where('batch_no', $batchNo)->first())
                        );

                        self::createBatchInfo(
                            $batchNo,
                            $newManageId,
                            $meanPirce,
                            $v['num'],
                            $materielInfo['id'],
                            $data['main_id'],
                            $data
                        );
                        MaterielsTypeModel::where('id', $v['type_id'])
                            ->update(['cost' => $meanPirce]);
                        $logInData[$k]['materiel_type_id'] = $goodsInfo['id'];//物料id
                        $logInData[$k]['materiel_name'] = $goodsInfo['materiel_name'];//物料名称
                        $logInData[$k]['type_name'] = $goodsInfo['type_name'];//物料型号
                        $logInData[$k]['materiel_no'] = $goodsInfo['materiel_no'];//物料编号
                        $logInData[$k]['materiel_class_id'] = $goodsClassInfo['id'];//物料二级分类主键名称
                        $logInData[$k]['materiel_class_name'] = $goodsClassInfo['class_name'];//物料二级分类名称
                        $logInData[$k]['materiel_class_no'] = $goodsClassInfo['class_no'];//物料二级分类编号
                        $logInData[$k]['curr_storage_manage_id'] = $newManageId;//库存id
                        $logInData[$k]['type'] = 0;//type;0:出库;1:调出;
                        $logInData[$k]['storage_id'] = $storageInfo['id'];//仓库主键id
                        $logInData[$k]['storage_name'] = $storageInfo['storage_name'];//仓库名
                        $logInData[$k]['storage_address'] = $storageInfo['storage_address'];//仓库地址
                        $logInData[$k]['operate_num'] = $v['num'];//操作数量
                        $logInData[$k]['last_storage_num'] = $storageManageInfo['in_storage_num'] ?? 0;//操作前库存数
                        $logInData[$k]['materiel_mean_cost'] = $v['unit_price'];//物料均价
                        $logInData[$k]['next_storage_num'] = isset($storageManageInfo['in_storage_num']) ? $storageManageInfo['in_storage_num'] + $v['num'] : $v['num'];//操作后库存数
                        $logInData[$k]['all_id_type'] = 3;//单据类型;0:无;1:报损;2:销售;
                        $logInData[$k]['all_id'] = $materielInfo['id'];//单据id
                        $logInData[$k]['in_storage_time'] = $data['purchase_time'];//出库时间
                        $logInData[$k]['remark'] = $iVal['remark'] ?? '';//备注
                        $logInData[$k]['user_id'] = $data['user_id'];//操作人用户id
                        $logInData[$k]['main_id'] = $data['main_id'];//主账号id
                        $logInData[$k]['shelf_id'] = $iVal['shelf_id'];
                        $logInData[$k]['location_id'] = $iVal['location_id'];
                        $logInData[$k]['batch_no'] = $batchNo;
                        $logInData[$k]['general_remarks'] = $data['general_remarks'] ?? '';//总备注
                        $logInData[$k]['created_at'] = time();
                        MessageService::sendInSms(
                            $materielInfo['purchase_no'],
                            $goodsInfo['materiel_name'],
                            $goodsInfo['type_name'],
                            $storageInfo['id'],
                            $storageInfo['storage_name'],
                            $data,
                            $v['num'],
                            $v['num'] + $storageManageInfo['in_storage_num']
                        );
                        $InlogReg .= '商品名称：' . $goodsInfo['materiel_name'] . '入库数量' . $v['num'] .
                            $goodsInfo['materiel_unit'] . '仓库：' . $v['storage_name'] . '、';

                        if (!empty($goodsInfo['is_product_materiel'])) {
                            MaterielTypeModel::where(['id' => $goodsInfo['id']])->update(['product_use_tag' => 1]);
                        }
                    }
                }
            }
            if (!empty($data['materiel_logistics_info'])) {//添加物流信息
                $logisticsIdArr = [];
                $materLogisticsInfo = json_decode($data['materiel_logistics_info'], true);
                if (is_array($materLogisticsInfo)) {
                    foreach ($materLogisticsInfo as $sVal) {
                        if (!empty($sVal['logistics_company']) && empty($sVal['logistics_order_no'])) {
                            throw new Exception('物流公司名称：' . $sVal['logistics_company'] . '物流号不能为空');
                        }
                        if (empty($sVal['logistics_company']) && !empty($sVal['logistics_order_no'])) {
                            throw new Exception('物流号：' . $sVal['logistics_order_no'] . '物流公司名称不能为空');
                        }
                        $logisticsData = [
                            'user_id' => $data['user_id'],
                            'main_id' => $data['main_id'],
                            'materiel_id' => $materielInfo['id'],
                            'logistics_company' => $sVal['logistics_company'],
                            'logistics_order_no' => $sVal['logistics_order_no'],
                        ];
                        if (!empty($sVal['id'])) {
                            $logisticsIdArr[] = $sVal['id'];
                            array_merge($logisticsData, ['updated_at' => Carbon::now()->timestamp]);
                            MaterielLogisticsInfoModel::where('id', $sVal['id'])->update($logisticsData);
                        } else {
                            array_merge($logisticsData, ['created_at' => Carbon::now()->timestamp]);
                            $id = MaterielLogisticsInfoModel::insertGetId($logisticsData);
                            $logisticsIdArr[] = $id;
                        }
                    }
                    if (!empty($logisticsIdArr)) {
                        MaterielLogisticsInfoModel::whereNotIn('id', $logisticsIdArr)->update(['delete_flag' => 1]);
                    }
                } else {
                    throw new Exception('物流信息异常');
                }
            }

            unset($data['batch_title']);
            unset($data['materiel_logistics_info']);

            //删除无用采购内容
            MaterielContentModel::whereIn('id', $uselessContentId)->delete();
            MaterielModel::where('id', $data['id'])->lockForUpdate()->update($data);
            MaterielContentModel::insert($needsToInsert);
            foreach ($needsToUpdate as $k2 => $v2) {
                $updData = $v2;
                unset($updData['id']);
                MaterielContentModel::where('id', $v2['id'])->lockForUpdate()->update($updData);
            }
            /*$checkData = [
                'check_person' => $data['approver_id']
            ];*/
            if (!empty($logInData)) {
                /*$checkData = [
                    'status' => 1,
                    'out_in_status' => 0,
                    'check_person' => $data['user_id'],
                    'eudit_status' => 1
                ];*/
                LogInstorageModel::insert($logInData);
                MaterielModel::where('id', $materielInfo['id'])->update(['in_storage_status' => 2]);
                CommonService::log('采购自动入库', $data, $InlogReg);
                /*$checkInfo = CheckModel::query()->where([
                    'type' => 3,
                    'all_id' => $materielInfo['id'],
                    'main_id' => $data['main_id']
                ])->first();
                if (!empty($checkInfo)) {
                    CheckModel::query()->where(['id'=>$checkInfo['id']])->delete();
                }*/
            }

            CommonService::log('修改采购单', $data, '采购单号:' . $materielInfo['purchase_no'] . '信息已更改！');
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('修改采购单:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    static public function add($data, $isUseShelf = 0, $isShareShelfLocation)
    {
        $logInData = [];
        $InlogReg = '';
        DB::beginTransaction();
        try {
            $materielContent = json_decode($data['materiel_content'], true, 512, JSON_THROW_ON_ERROR);
            unset($data['materiel_content']);
            //原金额(税前应付)
            $data['original_money'] = 0;
            foreach ($materielContent as $value) {
                $data['original_money'] += $value['unit_price'] * $value['num'];
            }
            //应付金额(修改价格或折扣优惠前金额)
            $data['real_money'] = $data['original_money'] + ($data['original_money'] * ($data['tax_rate'] / 100));
            /**
             * @preferential_way:优惠方式;0:无;1:修改价格;2:折扣优惠;
             * 优惠方式为非0值时，实付金额为修改后的金额或折扣优惠后的金额
             */
            switch ($data['preferential_way']) {
                case 0:
                    $data['final_money'] = $data['real_money'];
                    break;
                case 1:
                    $data['final_money'] = $data['preferential_money'];
                    break;
                case 2:
                    if ($data['preferential_money'] >= 100) {
                        throw new Exception('折扣比例不能超出百分百');
                    }
                    //折扣后
                    $afterDiscount = ($data['original_money'] * ($data['preferential_money'] / 100));
                    //税后
                    $afterTaxRate = $afterDiscount + ($afterDiscount * ($data['tax_rate'] / 100));
                    $data['final_money'] = ceil($afterTaxRate * 100) / 100;//物料均价
                    $data['discount'] = $data['preferential_money'];
                    break;
            }
            unset($data['preferential_money']);
            $data['general_remarks'] = $data['general_remarks'] ?? '';
            $data['purchase_time'] = strtotime($data['purchase_time']) ?? time();
            $data['created_at'] = time();
            $supplierInfo = SupplierCustomerModel::where([
                'id' => $data['supplier_customer_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->first();
            if (empty($supplierInfo)) {
                throw new Exception('供应商，没有找到！');
            }
            $data['supplier_customer_id'] = $supplierInfo['id'];
            /*  $data['deliver_person'] = $supplierInfo['name'];
             $data['deliver_phone'] = $supplierInfo['phone'];
             $data['deliver_address'] = $supplierInfo['address']; */
            $data['supplier_name'] = $supplierInfo['name'];
            $materData = $data;
            unset(
                $materData['mess_board_id'],
                $materData['batch_title'],
                $materData['materiel_logistics_info'],
                $materData['isUseShelf'],
                $materData['isShareShelfLocation']
            );

            $materielId = MaterielModel::query()->insertGetId($materData);
            if (!empty($data['mess_board_id']))
                MessBoardModel::query()->where([
                    'id' => $data['mess_board_id']
                ])->update([
                    'materiel_id' => $materielId,
                    'name' => $data['deliver_person'],
                    'phone' => $data['deliver_phone'],
                    'address' => $data['deliver_address'],
                ]);
            foreach ($materielContent as $k => $v) {
                $shelfId = 0;
                $locationId = 0;
                if (!empty($v['storage_id']) || !empty($data['is_auto_out_storage'])) {
                    //仓库信息
                    $storageInfo = StorageModel::where([
                        'id' => $v['storage_id'],
                        'main_id' => $data['main_id'],
                        'delete_flag' => 0,
                    ])->first();
                    if (empty($storageInfo)) {
                        throw new Exception('仓库`' . $v['storage_name'] . '`不存在');
                    }
                    if (empty($v['shelf_id']) || empty($v['location_id'])) {
                        if (!empty($isShareShelfLocation)) {
                            throw new Exception('您开启强制选择货架及库位，请选择！');
                        }
                        $sfData = ShelfService::get_default($v['storage_id']);
                        if (!empty($sfData)) {
                            $shelfId = $sfData['id'];
                            $lData = ShelfService::get_default($sfData['id'], 2);
                            $locationId = $lData['id'];
                        }
                        $v['shelf_id'] = $shelfId;
                        $v['location_id'] = $locationId;
                    } else {
                        $shelfId = $v['shelf_id'];
                        $locationId = $v['location_id'];
                    }
                }
                $goodsInfo = MaterielsTypeModel::where([
                    'id' => $v['type_id'],
                    'delete_flag' => 0,
                    'main_id' => $data['main_id']
                ])->first();
                $goodsClassInfo = MaterielClassModel::select(
                    'id',
                    'class_name',
                    'class_no',
                    'parent_id'
                )->where([
                    'id' => $goodsInfo['materiel_class_id'],
                    'delete_flag' => 0
                ])->first();
                if (empty($goodsClassInfo)) {
                    throw new Exception('商品:' . $goodsInfo['materiel_name'] . '的分类，没有找到！');
                }
                if (!empty($goodsInfo['is_use_serial']) && !empty($data['is_auto_out_storage'])) {
                    throw new Exception('商品:' . $goodsInfo['materiel_name'] . '已开启了序列号，不能开启自动出库');
                }

                $materielContent[$k]['type_id'] = $goodsInfo['id'];
                $materielContent[$k]['materiel_name'] = $goodsInfo['materiel_name'];
                $materielContent[$k]['type_name'] = $goodsInfo['type_name'];
                $materielContent[$k]['materiel_img'] = $goodsInfo['materiel_img'];
                $materielContent[$k]['materiel_no'] = $goodsInfo['materiel_no'];
                $materielContent[$k]['storage_name'] = $storageInfo['storage_name'] ?? '';
                $materielContent[$k]['storage_address'] = $storageInfo['storage_address'] ?? '';
                $materielContent[$k]['storage_id'] = $storageInfo['id'] ?? '';
                $materielContent[$k]['shelf_id'] = $shelfId ?? '';
                $materielContent[$k]['location_id'] = $locationId ?? '';
                $materielContent[$k]['remark'] = empty($v['remark']) ? '' : $v['remark'];
                $materielContent[$k]['materiel_id'] = $materielId;
                $materielContent[$k]['purchase_time'] = $data['purchase_time'];
                $materielContent[$k]['user_id'] = $data['user_id'];
                $materielContent[$k]['main_id'] = $data['main_id'];
                $materielContent[$k]['rest_num'] = $v['num'];
                $materielContent[$k]['created_at'] = time();
                //自动出库处理的逻辑
                if (!empty($data['is_auto_out_storage'])) {
                    if ($goodsInfo['is_product_materiel']) {
                        $materielContent[$k]['product_use_tag'] = 1;
                    }
                    $materielContent[$k]['rest_num'] = 0;
                    //物料当前库存信息
                    if ($isUseShelf) {
                        $storageManageInfo = StorageManageModel::where([
                            'type_id' => $goodsInfo['id'],
                            'storage_id' => $storageInfo['id'],
                            'main_id' => $data['main_id'],
                            'delete_flag' => 0,
                            'shelf_id' => $shelfId,
                            'location_id' => $locationId
                        ])->first();
                    } else {
                        $storageManageInfo = StorageManageModel::where([
                            'type_id' => $goodsInfo['id'],
                            'storage_id' => $storageInfo['id'],
                            'main_id' => $data['main_id'],
                            'delete_flag' => 0
                        ])->first();
                    }

                    $newManageId = $storageManageInfo['id'] ?? 0;
                    //检查库存中是否存在该物料
                    if (!empty($storageManageInfo)) {//存在
                        $meanPirce = sprintf("%.6f", (
                                ($storageManageInfo['materiel_mean_cost'] * $storageManageInfo['in_storage_num'])
                                + ($v['num'] * $v['unit_price']))
                            / ($storageManageInfo['in_storage_num'] + $v['num']));

                        StorageManageModel::where([
                            'id' => $storageManageInfo['id']
                        ])
                            ->update([
                                'in_storage_num' => $storageManageInfo['in_storage_num'] + $v['num'],
                                //'virtual_storage_num' => $storageManageInfo['virtual_storage_num'] + $v['num'],
                                'materiel_mean_cost' => $meanPirce
                            ]);
                    } else {//不存在
                        $meanPirce = 0;
                        $num = $v['num'] ?? 0;
                        if ($goodsInfo['cost'] != 0) {
                            $meanPirce = sprintf("%.6f", (
                                    ($goodsInfo['cost'] * $v['num']) +
                                    ($v['num'] * $v['unit_price'])) / $num);
                        } else {
                            $meanPirce = $v['unit_price'];
                        }

                        $newManageId = StorageManageModel::insertGetId([
                            'materiel_class_id' => $goodsClassInfo['id'],
                            'materiel_class_name' => $goodsClassInfo['class_name'],
                            'materiel_class_no' => $goodsClassInfo['class_no'],
                            'type_id' => $goodsInfo['id'],
                            'materiel_name' => $goodsInfo['materiel_name'],
                            'type_name' => $goodsInfo['type_name'],
                            'materiel_no' => $goodsInfo['materiel_no'],
                            'materiel_mean_cost' => $meanPirce,
                            'storage_id' => $storageInfo['id'],
                            'storage_name' => $storageInfo['storage_name'],
                            'storage_address' => $storageInfo['storage_address'],
                            'in_storage_num' => $v['num'],
                            //'virtual_storage_num' =>  $v['num'],
                            'main_id' => $data['main_id'],
                            'shelf_id' => $shelfId,
                            'location_id' => $locationId,
                            'is_product_materiel' => $goodsInfo['is_product_materiel'],
                            'in_storage_time' => $data['purchase_time'],
                            'created_at' => time()
                        ]);
                    }
                    do {
                        $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                    } while (
                        !empty(StorageBatchModel::where('main_id', $data['main_id'])
                            ->where('batch_no', $batchNo)->first())
                    );
                    self::createBatchInfo(
                        $batchNo,
                        $newManageId,
                        $meanPirce,
                        $v['num'],
                        $materielId,
                        $data['main_id'],
                        $data
                    );

                    MaterielsTypeModel::where('id', $v['type_id'])
                        ->update(['cost' => $meanPirce]);
                    $logInData[$k]['materiel_type_id'] = $goodsInfo['id'];//物料id
                    $logInData[$k]['materiel_name'] = $goodsInfo['materiel_name'];//物料名称
                    $logInData[$k]['type_name'] = $goodsInfo['type_name'];//物料型号
                    $logInData[$k]['materiel_no'] = $goodsInfo['materiel_no'];//物料编号
                    $logInData[$k]['materiel_class_id'] = $goodsClassInfo['id'];//物料二级分类主键名称
                    $logInData[$k]['materiel_class_name'] = $goodsClassInfo['class_name'];//物料二级分类名称
                    $logInData[$k]['materiel_class_no'] = $goodsClassInfo['class_no'];//物料二级分类编号
                    $logInData[$k]['curr_storage_manage_id'] = $newManageId;//库存id
                    $logInData[$k]['type'] = 0;//type;0:出库;1:调出;
                    $logInData[$k]['storage_id'] = $storageInfo['id'];//仓库主键id
                    $logInData[$k]['storage_name'] = $storageInfo['storage_name'];//仓库名
                    $logInData[$k]['storage_address'] = $storageInfo['storage_address'];//仓库地址
                    $logInData[$k]['operate_num'] = $v['num'];//操作数量
                    $logInData[$k]['last_storage_num'] = $storageManageInfo['in_storage_num'] ?? 0;//操作前库存数
                    $logInData[$k]['materiel_mean_cost'] = $v['unit_price'];//物料均价
                    $logInData[$k]['next_storage_num'] = isset($storageManageInfo['in_storage_num']) ? $storageManageInfo['in_storage_num'] + $v['num'] : $v['num'];//操作后库存数
                    $logInData[$k]['all_id_type'] = 3;//单据类型;0:无;1:报损;2:销售;
                    $logInData[$k]['all_id'] = $materielId;//单据id
                    $logInData[$k]['in_storage_time'] = $data['purchase_time'];//出库时间
                    $logInData[$k]['remark'] = $v['remark'] ?? '';//备注
                    $logInData[$k]['user_id'] = $data['user_id'];//操作人用户id
                    $logInData[$k]['main_id'] = $data['main_id'];//主账号id
                    $logInData[$k]['shelf_id'] = $shelfId;
                    $logInData[$k]['location_id'] = $locationId;
                    $logInData[$k]['batch_no'] = $batchNo;
                    $logInData[$k]['general_remarks'] = $data['general_remarks'] ?? '';//总备注
                    $logInData[$k]['created_at'] = time();
                    $sendNum = $v['num'];
                    if (isset($storageManageInfo['in_storage_num'])) {
                        $sendNum = $v['num'] + $storageManageInfo['in_storage_num'];
                    }
                    MessageService::sendInSms(
                        $data['purchase_no'],
                        $goodsInfo['materiel_name'],
                        $goodsInfo['type_name'],
                        $storageInfo['id'],
                        $storageInfo['storage_name'],
                        $data,
                        $v['num'],
                        $sendNum
                    );

                    $InlogReg .= '商品名称：' . $goodsInfo['materiel_name'] . '入库数量' . $v['num'] .
                        $goodsInfo['materiel_unit'] . '仓库：' . $v['storage_name'] . '、';

                }
            }

            if (!empty($data['materiel_logistics_info'])) {//添加物流信息
                $logisticsData = [];
                $materLogisticsInfo = json_decode($data['materiel_logistics_info'], true);
                if (is_array($materLogisticsInfo)) {
                    foreach ($materLogisticsInfo as $sVal) {
                        if (!empty($sVal['logistics_company']) && empty($sVal['logistics_order_no'])) {
                            throw new Exception('物流公司名称：' . $sVal['logistics_company'] . '物流号不能为空');

                        }
                        if (empty($sVal['logistics_company']) && !empty($sVal['logistics_order_no'])) {
                            throw new Exception('物流号：' . $sVal['logistics_order_no'] . '物流公司名称不能为空');
                        }
                        $logisticsData[] = [
                            'user_id' => $data['user_id'],
                            'main_id' => $data['main_id'],
                            'materiel_id' => $materielId,
                            'logistics_company' => $sVal['logistics_company'],
                            'logistics_order_no' => $sVal['logistics_order_no'],
                            'created_at' => Carbon::now()->timestamp
                        ];
                    }
                    if (!empty($logisticsData)) {
                        MaterielLogisticsInfoModel::insert($logisticsData);
                    }
                } else {
                    throw new Exception('物流信息异常');
                }
            }
            if (!empty($data['approver_id'])) {
                CheckModel::insert([
                    'type' => 3,
                    'all_id' => $materielId,
                    'main_id' => $data['main_id'],
                    'user_id' => $data['user_id'],
                    'status' => 0,
                    'out_in_status' => 0,
                    'check_person' => $data['approver_id'],
                    'order_no' => $data['purchase_no'],
                    'remark' => $data['general_remarks'] ?? '',
                    'created_at' => time(),
                    'eudit_status' => 0,
                ]);
            }
            if (!empty($logInData)) {
                /* CheckModel::where([
                     'type' => 3,
                     'all_id' => $materielId,
                     'main_id' => $data['main_id']
                 ])->update([
                     'status' => 1,
                     'out_in_status' => 0,
                     'check_person'=>$data['user_id'],
                     'eudit_status' => 1
                 ]);*/
                LogInstorageModel::insert($logInData);
                MaterielModel::where('id', $materielId)->update(['in_storage_status' => 2]);
                CommonService::log('采购自动入库', $data, $InlogReg);
            }
            MaterielContentModel::insert($materielContent);
            CommonService::log('新建采购单', $data, $InlogReg);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ['id' => $materielId]];
            //其他金额累加到实付和应付内
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('创建采购:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //添加套餐内容
    static public function addMaterielContent($materielContent, $materielId, $userId, $parentId, $purchaseTime)
    {
        foreach ($materielContent as $key => $value) {
            if (empty($value['type_id'])) {
                return ['code' => 1, 'msg' => '请选择物料产品', 'data' => ''];
            }

            if (empty($value['materiel_name'])) {
                return ['code' => 1, 'msg' => '物料名称缺失', 'data' => ''];
            }

//            if(empty($value['type_name'])) {
//                return ['code' => 1, 'msg' => '物料型号缺失', 'data' => ''];
//            }

            /* if(empty($value['storage_id'])) {
                return ['code' => 1, 'msg' => '请选择入库目标仓库', 'data' => ''];
            } */

            if (!isset($value['unit_price'])) {
                return ['code' => 1, 'msg' => '请填写物料单价', 'data' => ''];
            }

            if ($value['unit_price'] < 0) {
                return ['code' => 1, 'msg' => '物料单价只能为正数', 'data' => ''];
            }

//            if($value['num'] < 1) {
//                return ['code' => 1, 'msg' => '采购数量最少为1', 'data' => ''];
//            }

            $materielContent[$key]['materiel_id'] = $materielId;
            $materielContent[$key]['purchase_time'] = $purchaseTime;
            $materielContent[$key]['user_id'] = $userId;
            $materielContent[$key]['main_id'] = $parentId;
            $materielContent[$key]['rest_num'] = $value['num'];
        }

        MaterielContentModel::insert($materielContent);

        return true;
    }

    static public function materielInStorage($data)
    {
        $content = json_decode($data['content'], true);

        //采购单基础信息
        $materielInfo = MaterielModel::where('id', $content[0]['materiel_id'])->first();

        if ($materielInfo['repeal_status']) {
            return ['0' => 1, 'msg' => '采购单已撤销，无法重复操作', 'data' => ''];
        }

        if ($materielInfo['in_storage_status'] == 2) {
            return ['0' => 1, 'msg' => '已全部入库，无法重复操作', 'data' => ''];
        }
        if (strtotime($materielInfo['created_at']) > '1713506400') {//2024年4月19日 14点之前的订单不需要审核
            $checkInfo = CheckModel::where([
                'all_id' => $materielInfo['id'],
                'type' => 3,
                'repeal_status' => 0
            ])->first();
            if (!empty($checkInfo)) {
                if (empty($checkInfo['eudit_status'])) {
                    return ['code' => 1, 'msg' => '采购单在待审批中！', 'data' => ''];
                }
                if ($checkInfo['eudit_status'] == 2) {
                    return ['code' => 1, 'msg' => '采购单未审批通过！', 'data' => ''];
                }
            }
        }
        //status:入库状态：2-全部 1-部分
        switch ($data['status']) {
            case 1:
                $result = self::partInStorage($data, $content, $materielInfo);
                break;
            case 2:
                $result = self::partAllStorage($data, $content, $materielInfo);
                break;
        }

        return $result;
    }

    //部分入库
    static public function partInStorage($data, $content, $materielInfo)
    {
        $newStorageArr = [];//库存中不存在商品信息
        $existStorageArr = [];//库存中已存在商品信息
        $materielSerialNumberArr = [];//采购单序列号信息
        $storageManageArr = [];
        $logData = "";
        DB::beginTransaction();
        try {
            foreach ($content as $value) {
                $materielContentInfo = MaterielContentModel::getInfo($value['materiel_content_id']);
                if ($materielContentInfo['is_product_materiel']) {
                    MaterielTypeModel::query()->where([
                        'id' => $materielContentInfo['type_id']
                    ])
                        ->update(['product_use_tag' => 1]);
                }

                $storageInfo = StorageModel::where('id', $value['storage_id'])->first();

                if (empty($storageInfo) || $storageInfo['delete_flag'] == 1) {
                    throw new \Exception('仓库不存在！');
                }
                $logData .= '商品名称：' . $materielContentInfo['materiel_name'] . '入库数量' . $value['num'] . '仓库名：' . $storageInfo['storage_name'] . '、';
                /* if($materielContentInfo['is_product_materiel'] && $data['is_use_packages_components']){
                    if (!empty($value['serial_no'])) {
                        throw  new \Exception('套餐:'.$packageInfo['materiel_name'].'已开启序列号， 组件不能同步使用！');
                    }
                    //套餐与组件同步使用
                    $requestPackageInfo = [];
                    $requestPackageInfo ['id'] = $materielContentInfo['type_id'];
                    $requestPackageInfo ['materiel_name'] = $materielContentInfo['materiel_name'];
                    $requestPackageInfo ['shelf_id'] = $value['shelf_id'];
                    $requestPackageInfo ['location_id'] = $value['location_id'];
                    $requestPackageInfo ['storage_id'] = $value['storage_id'];
                    $requestPackageInfo ['num'] = $value['num'];
                    $data['all_id'] = $materielInfo['id'];
                    $data['operation_type'] = 0;
                    $data['all_id_type'] = 3;
                    StorageManageService::packageComponentHandle($requestPackageInfo, $data);
                    MaterielContentModel::where('id', $value['materiel_content_id'])
                        ->decrement('rest_num', $value['num']);
                    MaterielContentModel::where('id', $value['materiel_content_id'])
                        ->update(['storage_id' => $storageInfo['id'],
                            'storage_name' => $storageInfo['storage_name'],
                            'storage_address' => $storageInfo['storage_address'],
                            'shelf_id' => $value['shelf_id'],
                            'location_id' => $value['location_id']
                        ]);
                }else { */
                $storageManageInfo = StorageManageModel::getInfo(
                    $materielContentInfo['second_class_id'],
                    $materielContentInfo['type_id'],
                    $value['storage_id'],
                    $data['main_id'],
                );
                $shelfId = 0;
                $locationId = 0;
                if (empty($value['shelf_id']) || empty($value['location_id'])) {
                    if (!empty($data['is_share_shelf_location'])) {
                        return ['code' => 1, 'msg' => '您开启强制选择货架及库位，请选择！', 'data' => ''];
                    }
                    $sfData = ShelfService::get_default($value['storage_id']);
                    if (!empty($sfData)) {
                        $shelfId = $sfData['id'];
                        $lData = ShelfService::get_default($sfData['id'], 2);
                        $locationId = $lData['id'];
                    }
                    $value['shelf_id'] = $shelfId;
                    $value['location_id'] = $locationId;
                } else {
                    $shelfId = $value['shelf_id'];
                    $locationId = $value['location_id'];
                }
                //物料当前库存信息
                if ($data['is_use_shelf']) {
                    $storageManageInfo = StorageManageModel::where([
                        'type_id' => $materielContentInfo['type_id'],
                        'storage_id' => $storageInfo['id'],
                        'main_id' => $data['main_id'],
                        'delete_flag' => 0,
                        'shelf_id' => $shelfId,
                        'location_id' => $locationId
                    ])->first();
                } else {
                    $storageManageInfo = StorageManageModel::where([
                        'type_id' => $materielContentInfo['type_id'],
                        'storage_id' => $storageInfo['id'],
                        'main_id' => $data['main_id'],
                        'delete_flag' => 0
                    ])->first();
                }

                if (!empty($materielContentInfo['type_id'])) {
                    $materielTypeInfo = MaterielsTypeModel::where('id', $materielContentInfo['type_id'])->first();
                    if (!empty($materielTypeInfo)) {
                        if ($materielTypeInfo['is_use_serial'] == 1) {
                            if (empty($value['serial_no'])) {
                                return ['code' => 1, 'msg' => $materielTypeInfo['materiel_name'] . '的序列号，不能为空！', 'data' => ''];
                            }
                        }
                    }
                }
                //查询商品所有存在信息
                $inventoryInfo = StorageManageModel::query()->where([
                    'type_id' => $materielContentInfo['type_id'],
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0
                ])->select(
                    'materiel_mean_cost',
                    DB::raw('SUM(in_storage_num) as total_in_num')
                )->first();
                $meanPirce = $value['price'];
                if (!empty($inventoryInfo['materiel_mean_cost'])) {
                    $totalMoney = 0;
                    if (!empty($inventoryInfo['materiel_mean_cost']) && !empty($inventoryInfo['total_in_num'])) {
                        $totalMoney = $inventoryInfo['materiel_mean_cost'] * $inventoryInfo['total_in_num'];
                    }
                    $totalCost = 0;
                    if (!empty($value['num']) && !empty($value['price'])) {
                        $totalCost = $value['num'] * $value['price'];
                    }
                    $totalNum = $inventoryInfo['total_in_num'] + $value['num'];
                    $money = $totalMoney + $totalCost;
                    if (!empty($totalNum) && !empty($money)) {
                        $meanPirce = sprintf("%.6f", ($money)
                            /
                            ($totalNum));
                    }
                }
                $storageData = [
                    'materiel_content_id' => $materielContentInfo['id'],
                    'materiel_class_id' => $materielContentInfo['second_class_id'],
                    'materiel_class_name' => $materielContentInfo['second_class_name'],
                    'materiel_class_no' => $materielContentInfo['second_class_no'],
                    'type_id' => $materielContentInfo['type_id'],
                    'materiel_name' => $materielContentInfo['materiel_name'],
                    'type_name' => $materielContentInfo['type_name'],
                    'materiel_no' => $materielContentInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'remark' => empty($value['remark']) ? '' : $value['remark'],
                    'main_id' => $data['main_id'],
                    'serial_no' => !empty($value['serial_no']) ? $value['serial_no'] : "",
                    'batch_no' => !empty($value['batch_no']) ? $value['batch_no'] : "",
                    'inspector' => !empty($value['inspector']) ? $value['inspector'] : "",
                    'binding_supplier' => !empty($value['binding_supplier']) ? $value['binding_supplier'] : "",
                    'expiration_date' => !empty($value['expiration_date']) ? $value['expiration_date'] : "",
                    'warning_time' => !empty($value['warning_time']) ? $value['warning_time'] : "",
                    'production_time' => !empty($value['production_time']) ? $value['production_time'] : "",
                    'delivery_time' => !empty($value['delivery_time']) ? $value['delivery_time'] : "",
                    'production_order_number' => !empty($value['production_order_number']) ? $value['production_order_number'] : "",
                    'external_order_number' => !empty($value['external_order_number']) ? $value['external_order_number'] : "",
                    'materiel_mean_cost' => $meanPirce,
                    'in_storage_num' => $value['num'],
                    'then_cost' => $value['price'],
                    'created_at' => time(),
                    'in_storage_time' => !empty($data['in_storage_time']) ? strtotime($data['in_storage_time']) : time(),
                ];
                if (empty($storageManageInfo)) {
                    $storageData['virtual_storage_num'] = $value['num'];
                    $storageData['shelf_id'] = $value['shelf_id'];
                    $storageData['location_id'] = $value['location_id'];
                    $newStorageArr[] = $storageData;
                } else {
                    $storageData['storage_manage_id'] = $storageManageInfo['id'];
                    $storageData['virtual_storage_num'] = $storageManageInfo['virtual_storage_num'];
                    $storageData['shelf_id'] = $storageManageInfo['shelf_id'];
                    $storageData['location_id'] = $storageManageInfo['location_id'];
                    $storageData['request_cost'] = $value['price'];
                    $storageData['curr_storage_num'] = $storageManageInfo['in_storage_num'];
                    $existStorageArr[] = $storageData;
                }
                //添加采购序列号
                if (!empty($value['serial_no'])) {
                    $scondition['type_id'] = $materielContentInfo['type_id'];
                    $scondition['materiel_content_id'] = $materielContentInfo['id'];
                    $info = MaterielSerialNumberModel::select('serial_no')->where($scondition)->first();
                    $serialNoArr01 = explode(',', $value['serial_no']);
                    if ($value['num'] > count($serialNoArr01)) {
                        return ['code' => 1, 'msg' => '商品:' . $materielContentInfo['materiel_name'] . '所需序列号数量不足,' . '仍缺少:' . ($value['num'] - count($serialNoArr01)), 'data' => ''];
                    }
                    if ($value['num'] < count($serialNoArr01)) {
                        return ['code' => 1, 'msg' => '商品:' . $materielContentInfo['materiel_name'] . '序列号超出实际所需数量,' . '超出:' . (count($serialNoArr01) - $value['num']), 'data' => ''];
                    }
                    if (!empty($info['serial_no'])) {
                        $serialNoArr02 = explode(',', $info['serial_no']);
                        $res = array_intersect($serialNoArr01, $serialNoArr02);
                        if (!empty($res)) {
                            return ['code' => 1, 'msg' => '序列号，不允许重复', 'data' => ''];
                        }
                    }

                    if (!empty($storageManageInfo['id'])) {
                        foreach ($serialNoArr01 as $v1) {
                            $info = SerialNumberModel::select('a.serial_no')
                                ->from('serial_number as a')
                                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                                ->where([
                                    'serial_no' => $v1,
                                    'goods_id' => $materielContentInfo['type_id'],
                                    'a.delete_flag' => 0
                                ])->first();
                            if (!empty($info)) {
                                return ['code' => 1, 'msg' => '序列号:' . $v1 . '已存在', 'data' => ''];
                            }

                            $storageManageArr[] = [
                                'serial_no' => $v1,
                                'goods_id' => $materielContentInfo['type_id'],
                                'storage_manage_id' => $storageManageInfo['id'],
                                'created_at' => time(),
                                'main_id' => $data['main_id'],
                            ];
                        }
                    }

                    $materielSerialNumberArr[] = [
                        'serial_no' => $value['serial_no'],
                        'type_id' => $materielContentInfo['type_id'],
                        'materiel_content_id' => $materielContentInfo['id']
                    ];
                }
                /* } */
            }
            $existLogInfo = [];
            if (!empty($existStorageArr)) {
                foreach ($existStorageArr as $existVal) {
                    StorageManageModel::where('id', $existVal['storage_manage_id'])
                        ->update([
                            'in_storage_num' => $existVal['curr_storage_num'] + $existVal['in_storage_num'],
                            //'virtual_storage_num' => $existVal['virtual_storage_num'] + $existVal['in_storage_num'],
                        ]);

                    StorageManageModel::where('type_id', $existVal['type_id'])->update([
                        'materiel_mean_cost' => $existVal['materiel_mean_cost'],
                    ]);

                    $materielTypeInfo = MaterielsTypeModel::where('id', $existVal['type_id'])
                        ->first();

                    MaterielsTypeModel::where('id', $existVal['type_id'])
                        ->update([
                            'cost' => $existVal['materiel_mean_cost'],
                            'last_cost' => $materielTypeInfo['cost'],
                        ]);

                    MaterielContentModel::where('id', $existVal['materiel_content_id'])->decrement('rest_num', $existVal['in_storage_num']);
                    if (!empty($existVal['batch_no'])) {
                        $batchNo = $existVal['batch_no'];
                    } else {
                        $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';

                        do {
                            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                        } while (!empty(StorageBatchModel::where('main_id', $data['main_id'])
                            ->where('batch_no', $batchNo)->first()));
                    }
                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $existVal['storage_manage_id'],
                        $existVal['request_cost'],
                        $existVal['in_storage_num'],
                        0,
                        $data['main_id'],
                        $existVal
                    );
                    MaterielContentModel::where('id', $existVal['materiel_content_id'])
                        ->update(['storage_id' => $existVal['storage_id'],
                            'storage_name' => $existVal['storage_name'],
                            'storage_address' => $existVal['storage_address'],
                            'shelf_id' => $existVal['shelf_id'],
                            'location_id' => $existVal['location_id']
                        ]);
                    $existLogInfo = [
                        'type' => 0,
                        'storage_id' => $existVal['storage_id'],
                        'storage_name' => $existVal['storage_name'],
                        'storage_address' => $existVal['storage_address'],
                        'curr_storage_manage_id' => $existVal['storage_manage_id'],
                        'materiel_class_id' => $existVal['materiel_class_id'],
                        'materiel_class_name' => $existVal['materiel_class_name'],
                        'materiel_class_no' => $existVal['materiel_class_no'],
                        'materiel_type_id' => $existVal['type_id'],
                        'materiel_name' => $existVal['materiel_name'],
                        'type_name' => $existVal['type_name'],
                        'materiel_no' => $existVal['materiel_no'],
                        'purchase_no' => $materielInfo['purchase_no'],
                        'operate_num' => $existVal['in_storage_num'],
                        'last_storage_num' => $existVal['curr_storage_num'],
                        'next_storage_num' => $existVal['in_storage_num'] + $existVal['curr_storage_num'],
                        'materiel_mean_cost' => $existVal['then_cost'],
                        'remark' => empty($existVal['remark']) ? '' : $existVal['remark'],
                        'batch_id' => $batchId,
                        'all_id_type' => 3,
                        'all_id' => $materielInfo['id'],
                        'supplier_id' => $materielInfo['supplier_customer_id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => $data['in_storage_time'],
                        'created_at' => time(),
                        'serial_number' => $existVal['serial_no'],
                        'shelf_id' => $existVal['shelf_id'],
                        'location_id' => $existVal['location_id']
                    ];
                    $inLogId = LogInstorageModel::query()->insertGetId($existLogInfo);
                    MessageService::sendInSms(
                        $materielInfo['purchase_no'],
                        $existVal['materiel_name'],
                        $existVal['type_name'],
                        $existVal['storage_id'],
                        $existVal['storage_name'],
                        $data,
                        $existVal['in_storage_num'],
                        $existVal['in_storage_num'] + $existVal['curr_storage_num'],
                        $inLogId
                    );
                }
            }

            $newLogInfo = [];
            if (!empty($newStorageArr)) {
                foreach ($newStorageArr as $newVal) {
                    $newId = StorageManageModel::insertGetId([
                        'materiel_class_id' => $newVal['materiel_class_id'],
                        'materiel_class_name' => $newVal['materiel_class_name'],
                        'materiel_class_no' => $newVal['materiel_class_no'],
                        'type_id' => $newVal['type_id'],
                        'materiel_name' => $newVal['materiel_name'],
                        'type_name' => $newVal['type_name'],
                        'materiel_no' => $newVal['materiel_no'],
                        'materiel_mean_cost' => $newVal['materiel_mean_cost'],
                        'storage_id' => $newVal['storage_id'],
                        'storage_name' => $newVal['storage_name'],
                        'storage_address' => $newVal['storage_address'],
                        'in_storage_num' => $newVal['in_storage_num'],
                        //'virtual_storage_num' => $newVal['in_storage_num'],
                        'main_id' => $newVal['main_id'],
                        'in_storage_time' => $data['in_storage_time'],
                        'created_at' => time(),
                        'shelf_id' => $newVal['shelf_id'],
                        'location_id' => $newVal['location_id']
                    ]);
                    if (!empty($existVal['batch_no'])) {
                        $batchNo = $existVal['batch_no'];
                    } else {
                        $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';

                        do {
                            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                        } while (!empty(StorageBatchModel::where('main_id', $data['main_id'])
                            ->where('batch_no', $batchNo)->first()));
                    }
                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $newId,
                        $newVal['materiel_mean_cost'],
                        $newVal['in_storage_num'],
                        0,
                        $data['main_id'],
                        $newVal
                    );

                    MaterielsTypeModel::where('id', $newVal['type_id'])
                        ->update(['cost' => $newVal['materiel_mean_cost']]);


                    MaterielContentModel::where('id', $newVal['materiel_content_id'])
                        ->decrement('rest_num', $newVal['in_storage_num']);
                    MaterielContentModel::where('id', $newVal['materiel_content_id'])
                        ->update(['storage_id' => $newVal['storage_id'],
                            'storage_name' => $newVal['storage_name'],
                            'storage_address' => $newVal['storage_address'],
                            'shelf_id' => $newVal['shelf_id'],
                            'location_id' => $newVal['location_id']
                        ]);
                    $newLogInfo = [
                        'type' => 0,
                        'storage_id' => $newVal['storage_id'],
                        'storage_name' => $newVal['storage_name'],
                        'storage_address' => $newVal['storage_address'],
                        'curr_storage_manage_id' => $newId,
                        'materiel_class_id' => $newVal['materiel_class_id'],
                        'materiel_class_name' => $newVal['materiel_class_name'],
                        'materiel_class_no' => $newVal['materiel_class_no'],
                        'materiel_type_id' => $newVal['type_id'],
                        'materiel_name' => $newVal['materiel_name'],
                        'type_name' => $newVal['type_name'],
                        'materiel_no' => $newVal['materiel_no'],
                        'purchase_no' => $materielInfo['purchase_no'],
                        'operate_num' => $newVal['in_storage_num'],
                        'last_storage_num' => 0,
                        'batch_id' => $batchId,
                        'next_storage_num' => $newVal['in_storage_num'],
                        'materiel_mean_cost' => $newVal['then_cost'],
                        'remark' => isset($newVal['remark']) ? '' : $newVal['remark'],
                        'all_id_type' => 3,
                        'all_id' => $materielInfo['id'],
                        'supplier_id' => $materielInfo['supplier_customer_id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => $data['in_storage_time'],
                        'created_at' => time(),
                        'serial_number' => $newVal['serial_no'],
                        'shelf_id' => $newVal['shelf_id'],
                        'location_id' => $newVal['location_id']
                    ];
                    $inLogId = LogInstorageModel::query()->insertGetId($newLogInfo);
                    MessageService::sendInSms(
                        $materielInfo['purchase_no'],
                        $newVal['materiel_name'],
                        $newVal['type_name'],
                        $newVal['storage_id'],
                        $newVal['storage_name'],
                        $data,
                        $newVal['in_storage_num'],
                        $newVal['in_storage_num'],
                        $inLogId
                    );
                    //添加采购序列号
                    if (!empty($newVal['serial_no'])) {
                        $scondition['type_id'] = $newVal['type_id'];
                        $scondition['materiel_content_id'] = $materielContentInfo['id'];
                        $info = MaterielSerialNumberModel::select('serial_no')->where($scondition)->first();
                        $serialNoArr01 = explode(',', $value['serial_no']);
                        if (!empty($info['serial_no'])) {
                            $serialNoArr02 = explode(',', $info['serial_no']);
                            $res = array_intersect($serialNoArr01, $serialNoArr02);
                            if (!empty($res)) {
                                throw new Exception('采购序列号，不允许重复');
                            }
                        }
                        foreach ($serialNoArr01 as $v1) {
                            $info = SerialNumberModel::select('a.serial_no')
                                ->from('serial_number as a')
                                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                                ->where([
                                    'a.delete_flag' => 0,
                                    'serial_no' => $v1,
                                    'a.main_id' => $data['main_id']
                                ])->first();
                            if (!empty($info)) {
                                throw new Exception('序列号已存在。');
                            }
                            $storageManageArr[] = [
                                'serial_no' => $v1,
                                'goods_id' => $newVal['type_id'],
                                'storage_manage_id' => $newId,
                                'created_at' => time(),
                                'main_id' => $data['main_id'],
                            ];
                        }
                    }

                }
            }

            /* if (!empty($newLogInfo)) {
                 LogInstorageModel::insert($newLogInfo);
             }*/

            /*if (!empty($existLogInfo)) {
                LogInstorageModel::insert($existLogInfo);
            }*/

            $checkRestNum = MaterielContentModel::where('materiel_id', $materielInfo['id'])
                ->where('rest_num', '!=', 0)->get()->toArray();

            if (empty($checkRestNum)) {
                $status = 2;
                CheckModel::where([
                    'type' => 3,
                    'all_id' => $materielInfo['id'],
                    'main_id' => $data['main_id']
                ])->update([
                    'status' => 1,
                    'out_in_status' => 0,
                    'eudit_status' => 1
                ]);
            } else {
                $status = 1;
                CheckModel::where([
                    'type' => 3,
                    'all_id' => $materielInfo['id'],
                    'main_id' => $data['main_id']
                ])->update([
                    'out_in_status' => 1,
                    'eudit_status' => 1
                ]);
            }

            MaterielModel::where('id', $materielInfo['id'])->update(['in_storage_status' => $status]);
            if (!empty($materielSerialNumberArr)) {
                MaterielSerialNumberModel::insert($materielSerialNumberArr);
            }

            if (!empty($storageManageArr)) {
                SerialNumberModel::insert($storageManageArr);
            }
            CommonService::log('部分采购入库', $data, $logData);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('部分采购入库异常:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //全部入库
    static public function partAllStorage($data, $content, $materielInfo)
    {
        $newStorageArr = [];//库存中不存在商品信息
        $existStorageArr = [];//库存中已存在商品信息
        $materielSerialNumberArr = [];//采购单序列号信息
        $storageManageArr = [];
        $logData = "";
        foreach ($content as $value) {
            $materielContentInfo = MaterielContentModel::select(
                'a.id',
                'a.type_id',
                'a.rest_num',
                'b.materiel_name',
                'b.type_name',
                'b.materiel_no',
                'b.materiel_img',
                'c.id as second_class_id',
                'c.class_name as second_class_name',
                'c.class_no as second_class_no',
                'd.id as first_class_id',
                'd.class_name as first_class_name',
                'e.purchase_no',
                'b.is_product_materiel'
            )
                ->from('materiel_content as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel as e', 'e.id', '=', 'a.materiel_id')
                ->where('a.id', $value['materiel_content_id'])
                ->first();

            if ($materielContentInfo['is_product_materiel']) {
                MaterielTypeModel::where([
                    'id' => $materielContentInfo['type_id']
                ])
                    ->update(['product_use_tag' => 1]);
            }

            $storageInfo = StorageModel::where('id', $value['storage_id'])->first();

            if (empty($storageInfo) || $storageInfo['delete_flag'] == 1) {
                return ['code' => 1, 'msg' => '仓库不存在,无法入库', 'data' => ''];
            }
            $logData .= '商品名称：' . $materielContentInfo['materiel_name'] . '入库数量' . $value['num'] . '仓库名：' . $storageInfo['storage_name'] . '、';
            /* if($materielContentInfo['is_product_materiel'] && $data['is_use_packages_components']){
                 //套餐与组件同步使用
                 if (!empty($value['serial_no'])) {
                     throw  new \Exception('套餐:'.$materielContentInfo['materiel_name'].'已开启序列号， 组件不能同步使用！');
                 }
                 $requestPackageInfo = [];
                 $requestPackageInfo ['id'] = $materielContentInfo['type_id'];
                 $requestPackageInfo ['materiel_name'] = $materielContentInfo['materiel_name'];
                 $requestPackageInfo ['shelf_id'] = $value['shelf_id'];
                 $requestPackageInfo ['location_id'] = $value['location_id'];
                 $requestPackageInfo ['storage_id'] = $value['storage_id'];
                 $requestPackageInfo ['num'] = $value['num'];
                 $data['operation_type'] = 0;
                 $data['all_id_type'] = 3;
                 StorageManageService::packageComponentHandle($requestPackageInfo, $data);
                 MaterielContentModel::where('id', $value['materiel_content_id'])->decrement('rest_num', $materielContentInfo['rest_num']);
             }else {*/
            if (empty($value['shelf_id']) || empty($value['location_id'])) {
                if (!empty($data['is_share_shelf_location'])) {
                    return ['code' => 1, 'msg' => '您开启强制选择货架及库位，请选择！', 'data' => ''];
                }
                $shelfId = 0;
                $locationId = 0;
                $sfData = ShelfService::get_default($value['storage_id']);
                if (!empty($sfData)) {
                    $shelfId = $sfData['id'];
                    $lData = ShelfService::get_default($sfData['id'], 2);
                    $locationId = $lData['id'];
                }
                $value['shelf_id'] = $shelfId;
                $value['location_id'] = $locationId;
            } else {
                $shelfId = $value['shelf_id'];
                $locationId = $value['location_id'];
            }
            //物料当前库存信息
            if ($data['is_use_shelf']) {
                $storageManageInfo = StorageManageModel::where([
                    'type_id' => $materielContentInfo['type_id'],
                    'storage_id' => $storageInfo['id'],
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0,
                    'shelf_id' => $shelfId,
                    'location_id' => $locationId
                ])->first();
            } else {
                $storageManageInfo = StorageManageModel::where([
                    'type_id' => $materielContentInfo['type_id'],
                    'storage_id' => $storageInfo['id'],
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0
                ])->first();
            }
            if (!empty($materielContentInfo['type_id'])) {
                $materielTypeInfo = MaterielsTypeModel::where('id', $materielContentInfo['type_id'])->first();
                if (!empty($materielTypeInfo)) {
                    if ($materielTypeInfo['is_use_serial'] == 1) {
                        if (empty($value['serial_no'])) {
                            return ['code' => 1, 'msg' => '商品' . $materielTypeInfo['materiel_name'] . '的序列号，不能为空！', 'data' => ''];
                        }
                    }
                }
            }

            //查询商品所有存在信息
            $inventoryInfo = StorageManageModel::query()->where([
                'type_id' => $materielContentInfo['type_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->select(
                'materiel_mean_cost',
                DB::raw('SUM(in_storage_num) as total_in_num')
            )->first();
            $meanPirce = $value['price'];
            if (!empty($inventoryInfo['materiel_mean_cost'])) {
                $totalMoney = 0;
                if (!empty($inventoryInfo['materiel_mean_cost']) && !empty($inventoryInfo['total_in_num'])) {
                    $totalMoney = $inventoryInfo['materiel_mean_cost'] * $inventoryInfo['total_in_num'];
                }
                $totalCost = 0;
                if (!empty($materielContentInfo['num']) && !empty($value['price'])) {
                    $totalCost = $materielContentInfo['num'] * $value['price'];
                }
                $totalNum = $inventoryInfo['total_in_num'] + $materielContentInfo['rest_num'];
                $money = $totalMoney + $totalCost;
                if (!empty($totalNum) && !empty($money)) {
                    $meanPirce = sprintf("%.6f", ($money)
                        /
                        ($totalNum));
                }
            }
            if (empty($storageManageInfo) || $storageManageInfo['delete_flag'] == 1) {
                $materielTypeInfo = MaterielsTypeModel::where('id', $materielContentInfo['type_id'])->first();
                /*$meanPirce = 0;
                $num = $value['num'] == 0 ? 1 : $value['num'];
                if ($materielTypeInfo['cost'] != 0) {
                    $meanPirce = sprintf("%.6f",
                        (
                            ($materielTypeInfo['cost'] * $value['num'])
                            +
                            ($value['num'] * $value['price'])
                        )
                        / $num);
                } else {
                    $meanPirce = $value['price'];
                }*/
                $newStorageArr[] = [
                    'materiel_content_id' => $materielContentInfo['id'],
                    'materiel_class_id' => $materielContentInfo['second_class_id'],
                    'materiel_class_name' => $materielContentInfo['second_class_name'],
                    'materiel_class_no' => $materielContentInfo['second_class_no'],
                    'type_id' => $materielContentInfo['type_id'],
                    'materiel_name' => $materielContentInfo['materiel_name'],
                    'type_name' => $materielContentInfo['type_name'],
                    'materiel_no' => $materielContentInfo['materiel_no'],
                    'materiel_mean_cost' => $meanPirce,
                    'remark' => empty($value['remark']) ? '' : $value['remark'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $materielContentInfo['rest_num'],
                    'main_id' => $data['main_id'],
                    'then_cost' => $value['price'],
                    'serial_no' => !empty($value['serial_no']) ? $value['serial_no'] : "",
                    'batch_no' => !empty($value['batch_no']) ? $value['batch_no'] : "",
                    'inspector' => !empty($value['inspector']) ? $value['inspector'] : "",
                    'binding_supplier' => !empty($value['binding_supplier']) ? $value['binding_supplier'] : "",
                    'expiration_date' => !empty($value['expiration_date']) ? $value['expiration_date'] : "",
                    'warning_time' => !empty($value['warning_time']) ? $value['warning_time'] : "",
                    'production_time' => !empty($value['production_time']) ? $value['production_time'] : "",
                    'delivery_time' => !empty($value['delivery_time']) ? $value['delivery_time'] : "",
                    'production_order_number' => !empty($value['production_order_number']) ? $value['production_order_number'] : "",
                    'external_order_number' => !empty($value['external_order_number']) ? $value['external_order_number'] : "",
                ];
            } else {
                /* $meanPirce = sprintf("%.6f",
                     (
                         ($storageManageInfo['materiel_mean_cost'] * $storageManageInfo['in_storage_num'])
                         +
                         ($materielContentInfo['num'] * $value['price'])
                     )
                     /
                     ($storageManageInfo['in_storage_num'] + $materielContentInfo['rest_num']));*/

                $existStorageArr[] = [
                    'storage_manage_id' => $storageManageInfo['id'],
                    'materiel_mean_cost' => $meanPirce,
                    'materiel_content_id' => $materielContentInfo['id'],
                    'materiel_class_id' => $materielContentInfo['second_class_id'],
                    'materiel_class_name' => $materielContentInfo['second_class_name'],
                    'materiel_class_no' => $materielContentInfo['second_class_no'],
                    'type_id' => $materielContentInfo['type_id'],
                    'materiel_name' => $materielContentInfo['materiel_name'],
                    'type_name' => $materielContentInfo['type_name'],
                    'materiel_no' => $materielContentInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $materielContentInfo['rest_num'],
                    'remark' => empty($value['remark']) ? '' : $value['remark'],
                    //'virtual_storage_num' => $storageManageInfo['virtual_storage_num'],
                    'main_id' => $data['main_id'],
                    'in_storage_time' => time(),
                    'created_at' => time(),
                    'then_cost' => $value['price'],
                    'curr_storage_num' => $storageManageInfo['in_storage_num'],
                    'serial_no' => !empty($value['serial_no']) ? $value['serial_no'] : "",
                    'batch_no' => !empty($value['batch_no']) ? $value['batch_no'] : "",
                    'inspector' => !empty($value['inspector']) ? $value['inspector'] : "",
                    'binding_supplier' => !empty($value['binding_supplier']) ? $value['binding_supplier'] : "",
                    'expiration_date' => !empty($value['expiration_date']) ? $value['expiration_date'] : "",
                    'warning_time' => !empty($value['warning_time']) ? $value['warning_time'] : "",
                    'production_time' => !empty($value['production_time']) ? $value['production_time'] : "",
                    'delivery_time' => !empty($value['delivery_time']) ? $value['delivery_time'] : "",
                    'production_order_number' => !empty($value['production_order_number']) ? $value['production_order_number'] : "",
                    'external_order_number' => !empty($value['external_order_number']) ? $value['external_order_number'] : "",
                ];
            }
            //添加采购序列号
            if (!empty($value['serial_no'])) {
                $scondition['type_id'] = $materielContentInfo['type_id'];
                $scondition['materiel_content_id'] = $materielContentInfo['id'];
                $info = MaterielSerialNumberModel::select('serial_no')->where($scondition)->first();
                $serialNoArr02 = explode(',', $info['serial_no']);
                if (!empty($info['serial_no'])) {
                    $serialNoArr01 = explode(',', $value['serial_no']);
                    $res = array_intersect($serialNoArr01, $serialNoArr02);
                    if (!empty($res)) {
                        return ['code' => 1, 'msg' => '采购序列号，不允许重复', 'data' => ''];
                    }
                }
                if (!empty($storageManageInfo['id'])) {
                    foreach ($serialNoArr01 as $v1) {
                        $info = SerialNumberModel::select('a.serial_no')
                            ->from('serial_number as a')
                            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                            ->where([
                                'a.delete_flag' => 0,
                                'serial_no' => $v1,
                                'goods_id' => $materielContentInfo['type_id']
                            ])->first();
                        if (!empty($info)) {
                            return ['code' => 1, 'msg' => '序列号' . $v1 . '已存在。', 'data' => ''];
                        }
                        $storageManageArr[] = [
                            'serial_no' => $v1,
                            'goods_id' => $materielContentInfo['type_id'],
                            'storage_manage_id' => $storageManageInfo['id'],
                            'created_at' => time(),
                            'main_id' => $data['main_id'],
                        ];
                    }
                }
                $materielSerialNumberArr[] = [
                    'serial_no' => $value['serial_no'],
                    'type_id' => $materielContentInfo['type_id'],
                    'materiel_content_id' => $materielContentInfo['id']
                ];
            }
            /*  }*/
        }
        DB::beginTransaction();
        try {
            $existLogInfo = [];
            if (!empty($existStorageArr)) {
                foreach ($existStorageArr as $existVal) {
//                    StorageManageModel::where('type_id', $existVal['type_id'])
//                        ->where(['main_id' => $data['main_id']])
//                        ->increment('in_storage_num', $existVal['in_storage_num'],
//                        ['materiel_mean_cost' => $existVal['materiel_mean_cost']]
//                    );

                    StorageManageModel::where('id', $existVal['storage_manage_id'])
                        ->update([
                            'in_storage_num' => $existVal['curr_storage_num'] + $existVal['in_storage_num'],
                            //'virtual_storage_num' => $existVal['virtual_storage_num'] + $existVal['in_storage_num'],
                            'delete_flag' => 0
                        ]);

                    StorageManageModel::where('type_id', $existVal['type_id'])->update([
                        'materiel_mean_cost' => $existVal['materiel_mean_cost'],
                    ]);

                    MaterielsTypeModel::where('id', $existVal['type_id'])
                        ->update(['cost' => $existVal['materiel_mean_cost']]);

                    MaterielContentModel::where('id', $existVal['materiel_content_id'])->decrement('rest_num', $existVal['in_storage_num']);
                    MaterielContentModel::where('id', $existVal['materiel_content_id'])
                        ->update(['storage_manage_id' => $existVal['storage_manage_id']]);
                    if (!empty($existVal['batch_no'])) {
                        $batchNo = $existVal['batch_no'];
                    } else {
                        $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';

                        do {
                            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                        } while (!empty(StorageBatchModel::where('main_id', $data['main_id'])
                            ->where('batch_no', $batchNo)->first()));
                    }
                    $existLogInfo = [
                        'type' => 0,
                        'storage_id' => $existVal['storage_id'],
                        'storage_name' => $existVal['storage_name'],
                        'storage_address' => $existVal['storage_address'],
                        'curr_storage_manage_id' => $existVal['storage_manage_id'],
                        'materiel_class_id' => $existVal['materiel_class_id'],
                        'materiel_class_name' => $existVal['materiel_class_name'],
                        'materiel_class_no' => $existVal['materiel_class_no'],
                        'materiel_type_id' => $existVal['type_id'],
                        'materiel_name' => $existVal['materiel_name'],
                        'type_name' => $existVal['type_name'],
                        'materiel_no' => $existVal['materiel_no'],
                        'purchase_no' => $materielInfo['purchase_no'],
                        'operate_num' => $existVal['in_storage_num'],
                        'last_storage_num' => $existVal['curr_storage_num'],
                        'next_storage_num' => $existVal['in_storage_num'] + $existVal['curr_storage_num'],
                        'materiel_mean_cost' => $existVal['then_cost'],
                        'remark' => empty($existVal['remark']) ? '' : $existVal['remark'],
                        'all_id_type' => 3,
                        'batch_no' => $batchNo,
                        'all_id' => $materielInfo['id'],
                        'supplier_id' => $materielInfo['supplier_customer_id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => strtotime($data['in_storage_time']),
                        'created_at' => time(),
                        'serial_number' => $existVal['serial_no']
                    ];
                    $inLogId = LogInstorageModel::query()->insertGetId($existLogInfo);
                    self::createBatchInfo(
                        $batchNo,
                        $existVal['storage_manage_id'],
                        $existVal['materiel_mean_cost'],
                        $existVal['in_storage_num'],
                        $materielInfo['id'],
                        $data['main_id'],
                        $existVal
                    );

                    MessageService::sendInSms(
                        $materielInfo['purchase_no'],
                        $existVal['materiel_name'],
                        $existVal['type_name'],
                        $existVal['storage_id'],
                        $existVal['storage_name'],
                        $data,
                        $existVal['in_storage_num'],
                        $existVal['in_storage_num'],
                        $inLogId
                    );
                }
            }

            $newLogInfo = [];
            if (!empty($newStorageArr)) {
                foreach ($newStorageArr as $newVal) {
                    $newId = StorageManageModel::insertGetId([
                        'materiel_class_id' => $newVal['materiel_class_id'],
                        'materiel_class_name' => $newVal['materiel_class_name'],
                        'materiel_class_no' => $newVal['materiel_class_no'],
                        'type_id' => $newVal['type_id'],
                        'materiel_name' => $newVal['materiel_name'],
                        'type_name' => $newVal['type_name'],
                        'materiel_no' => $newVal['materiel_no'],
                        'materiel_mean_cost' => $newVal['materiel_mean_cost'],
                        'storage_id' => $newVal['storage_id'],
                        'storage_name' => $newVal['storage_name'],
                        'storage_address' => $newVal['storage_address'],
                        'in_storage_num' => $newVal['in_storage_num'],
                        //'virtual_storage_num' =>  $newVal['in_storage_num'],
                        'main_id' => $newVal['main_id'],
                        'in_storage_time' => time(),
                        'created_at' => time()
                    ]);
                    if (!empty($newVal['batch_no'])) {
                        $batchNo = $newVal['batch_no'];
                    } else {
                        $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';

                        do {
                            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                        } while (!empty(StorageBatchModel::where('main_id', $data['main_id'])
                            ->where('batch_no', $batchNo)->first()));
                    }
                    self::createBatchInfo(
                        $batchNo,
                        $newId,
                        $newVal['materiel_mean_cost'],
                        $newVal['in_storage_num'],
                        $materielInfo['id'],
                        $data['main_id'],
                        $newVal
                    );

                    StorageManageModel::where('type_id', $newVal['type_id'])->update([
                        'materiel_mean_cost' => $newVal['materiel_mean_cost']
                    ]);

                    MaterielsTypeModel::where('id', $newVal['type_id'])
                        ->update(['cost' => $newVal['materiel_mean_cost']]);

                    MaterielContentModel::where('id', $newVal['materiel_content_id'])
                        ->decrement('rest_num', $newVal['in_storage_num']);
                    MaterielContentModel::where('id', $newVal['materiel_content_id'])
                        ->update(['storage_manage_id' => $newId]);


                    $newLogInfo = [
                        'type' => 0,
                        'storage_id' => $newVal['storage_id'],
                        'storage_name' => $newVal['storage_name'],
                        'storage_address' => $newVal['storage_address'],
                        'curr_storage_manage_id' => $newId,
                        'materiel_class_id' => $newVal['materiel_class_id'],
                        'materiel_class_name' => $newVal['materiel_class_name'],
                        'materiel_class_no' => $newVal['materiel_class_no'],
                        'materiel_type_id' => $newVal['type_id'],
                        'materiel_name' => $newVal['materiel_name'],
                        'type_name' => $newVal['type_name'],
                        'materiel_no' => $newVal['materiel_no'],
                        'purchase_no' => $materielInfo['purchase_no'],
                        'operate_num' => $newVal['in_storage_num'],
                        'last_storage_num' => 0,
                        'next_storage_num' => $newVal['in_storage_num'],
                        'materiel_mean_cost' => $newVal['then_cost'],
                        'remark' => empty($newVal['remark']) ? '' : $newVal['remark'],
                        'all_id_type' => 3,
                        'batch_no' => $batchNo,
                        'all_id' => $materielInfo['id'],
                        'supplier_id' => $materielInfo['supplier_customer_id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => strtotime($data['in_storage_time']),
                        'created_at' => time(),
                        'serial_number' => $newVal['serial_no']
                    ];
                    $inLogId = LogInstorageModel::query()->insertGetId($newLogInfo);
                    MessageService::sendInSms(
                        $materielInfo['purchase_no'],
                        $newVal['materiel_name'],
                        $newVal['type_name'],
                        $newVal['storage_id'],
                        $newVal['storage_name'],
                        $data,
                        $newVal['in_storage_num'],
                        $newVal['in_storage_num'],
                        $inLogId
                    );
                    //添加采购序列号
                    if (!empty($newVal['serial_no'])) {

                        $scondition['type_id'] = $newVal['type_id'];
                        $scondition['materiel_content_id'] = $materielContentInfo['id'];

                        $info = MaterielSerialNumberModel::select('serial_no')->where($scondition)->first();
                        $serialNoArr01 = explode(',', $value['serial_no']);


                        if (!empty($info['serial_no'])) {

                            $serialNoArr02 = explode(',', $info['serial_no']);

                            $res = array_intersect($serialNoArr01, $serialNoArr02);

                            if (!empty($res)) {

                                return ['code' => 1, 'msg' => '采购序列号，不允许重复', 'data' => ''];
                            }
                        }

                        foreach ($serialNoArr01 as $v1) {
                            $info = SerialNumberModel::select('a.serial_no')
                                ->from('serial_number as a')
                                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                                ->where([
                                    'a.delete_flag' => 0,
                                    'serial_no' => $v1,
                                    'a.main_id' => $data['main_id']
                                ])->first();
                            if (!empty($info)) {

                                return ['code' => 1, 'msg' => '序列号已存在。', 'data' => ''];
                            }
                            $storageManageArr[] = [
                                'serial_no' => $v1,
                                'goods_id' => $newVal['type_id'],
                                'storage_manage_id' => $newId,
                                'created_at' => time(),
                                'main_id' => $data['main_id'],
                            ];
                        }
                    }
                }
            }

            /* if (!empty($newLogInfo)) {
                 LogInstorageModel::insert($newLogInfo);
             }

             if (!empty($existLogInfo)) {
                 LogInstorageModel::insert($existLogInfo);
             }*/

            MaterielModel::where('id', $materielInfo['id'])->update(['in_storage_status' => 2]);

            CheckModel::where([
                'type' => 3,
                'all_id' => $materielInfo['id'],
                'main_id' => $data['main_id']
            ])->update([
                'status' => 1,
                'out_in_status' => 0,
                'eudit_status' => 1
            ]);
            if (!empty($materielSerialNumberArr)) {
                MaterielSerialNumberModel::insert($materielSerialNumberArr);
            }
            if (!empty($storageManageArr)) {
                SerialNumberModel::insert($storageManageArr);
            }
            CommonService::log('全部采购入库', $data, $logData);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('全部采购入库异常:' . var_export($e->getMessage(), true));
            return [];
        }
    }

    static public function list($data, $userId)
    {
        if (!empty($data['keyword'])) {//关键词搜索组是否启用
            $result = self::withKeyword($userId, $data);
        } else {
            $result = self::search($userId, $data);
        }
        return $result;
    }

    static public function newList($data, $userId)
    {
        if (!empty($data['keyword'])) {//关键词搜索组是否启用
            $result = self::withKeyword($userId, $data);
        } else {
            $result = self::search($userId, $data);
        }
        if(!empty($result['data'])){
            foreach ($result['data'] as &$value){
                if (!empty($value['materiel_content'])) {
                    $goodsData = [];
                    foreach ($value['materiel_content'] as $iVal) {
                        $goodsData[] = [
                            'materiel_name' => $iVal['materiel_name'],
                            'materiel_img' => $iVal['materiel_img']
                        ];
                    }
                    $newGoodsData = [];
                    $goodsArr = array_map("unserialize", array_unique(array_map("serialize", $goodsData)));
                    foreach ($goodsArr as $val) {
                        $totalGoodsNum = 0;
                        $totalGoodsPrice = 0;
                        foreach ($value['materiel_content'] as $lVal) {
                            if ($val['materiel_name'] === $lVal['materiel_name']) {
                                $val['goods_list'][] = $lVal;
                                $totalGoodsNum += $lVal['num'];
                                $totalGoodsPrice += $lVal['num'] * $lVal['unit_price'];
                            }
                        }
                        $val['total_goods_num'] = $totalGoodsNum;
                        $val['total_goods_price'] = $totalGoodsPrice;
                        $newGoodsData[] = $val;
                    }
                    $value['materiel_content'] = $newGoodsData;
                }
            }
        }
        return $result;
    }

    static private function withKeyword($userId, $data)
    {
        $materielIdInfo = [];
        switch ($data['search_type']) {
            case 0:
                $condition[] = ['b.type_name', 'like', '%' . $data['keyword'] . '%'];
                $materielIdInfo = MaterielContentModel::getMaterielId($condition, $userId);
                break;
            //商品名
            case 1:
                $condition[] = ['b.materiel_name', 'like', '%' . $data['keyword'] . '%'];
                $materielIdInfo = MaterielContentModel::getMaterielId($condition, $userId);
                break;
            //商品编号
            case 2:
                $condition[] = ['b.materiel_no', 'like', '%' . $data['keyword'] . '%'];
                $materielIdInfo = MaterielContentModel::getMaterielId($condition, $userId);
                break;
            //内部单号
            case 3:
                $condition[] = ['purchase_no', 'like', '%' . $data['keyword'] . '%'];
                $materielIdInfo = MaterielModel::getMaterielId($condition, $data);
                break;
            //外部单号
            case 4:
                $condition[] = ['out_order_no', 'like', '%' . $data['keyword'] . '%'];
                $materielIdInfo = MaterielModel::getMaterielId($condition, $data);
                break;
            //快递单号
            case 5:
                //$condition[] = ['logistics_order_no', 'like', '%'.$data['keyword'].'%'];
                $materielIdInfo = MaterielModel::getlogisticsInfo($data, $userId);

                break;
            //供应商
            case 6:
                $condition[] = ['supplier_name', 'like', '%' . $data['keyword'] . '%'];
                $materielIdInfo = MaterielModel::getMaterielId($condition, $data);
                break;
            //司机名称
//            case 7:
//                $condition[] = ['logistics_order_no', 'like', '%'.$data['keyword'].'%'];
//                $materielIdInfo = MaterielsModel::getMaterielId($condition, $userId);
//                break;
            //发货人
            case 8:
                $condition[] = ['deliver_person', 'like', '%' . $data['keyword'] . '%'];
                $materielIdInfo = MaterielModel::getMaterielId($condition, $userId);
                break;
        }
        $materielIdArr = ['无值'];
        if (!empty($materielIdInfo)) {
            foreach ($materielIdInfo as $value) {
                $materielIdArr[] = $value['materiel_id'];
            }
        }

        return self::search($userId, $data, $materielIdArr);
    }

    //无搜索条件-默认检索
    static private function search($userId, $data, $materielIdArr = [])
    {
        $query = MaterielModel::select(
            'a.id',
            'repeal_status',
            'purchase_time',
            'supplier_name',
            'final_money',
            'out_order_no',
            'purchase_no',
            'pay_status',
            'in_storage_status',
            'username',
            'nickname',
            'a.supplier_customer_id'
        )
            ->from('materiel as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->with('materielContent', function ($query) {
                $query->select(
                    'materiel_content.id',
                    'materiel_id',
                    'unit_price',
                    'num',
                    'rest_num',
                    'a.materiel_name',
                    'a.type_name',
                    'a.materiel_no',
                    'a.materiel_img',
                    'materiel_content.shelf_id',
                    'materiel_content.location_id',
                    's.shelf_name',
                    'l.location_name',
                )
                    ->leftJoin('materiel_type as a', 'a.id', '=', 'materiel_content.type_id')
                    ->leftJoin('storage_shelf as s', 'materiel_content.shelf_id', '=', 's.id')
                    ->leftJoin('storage_shelf_location as l', 'materiel_content.location_id', '=', 'l.id');
            })
            ->where('repeal_status', $data['repeal_status'])
            ->where('a.delete_flag', 0)
            ->where($userId);

        if (!empty($data['start_time'])) {
            $startTimeArr = explode(' ', $data['start_time']);
            $startTime = strtotime($startTimeArr[0] . ' 00:00:00');
        }

        if (!empty($data['end_time'])) {
            $endTimeArr = explode(' ', $data['end_time']);
            $endTime = strtotime($endTimeArr[0] . ' 23:59:59');
        }

        if (!empty($startTime) && !empty($endTime)) {
            $query->whereBetween('purchase_time', [$startTime, $endTime]);
        } else if (!empty($startTime) && empty($endTime)) {
            $query->where('purchase_time', '>=', $startTime);
        } else if (empty($startTime) && !empty($endTime)) {
            $query->where('purchase_time', '<=', $endTime);
        }

        //销售单状态
        switch ($data['status']) {
            //新订单
            case 1:
                $query->where('pay_status', 0);
                $query->where('in_storage_status', 0);
                break;
            //已付款(未入库)
            case 2:
                $query->whereIn('pay_status', [1, 2]);
                $query->where('in_storage_status', 0);
                break;
            //已完结（已付款，已入库）
            case 3:
                $query->where('pay_status', 2);
                $query->where('in_storage_status', 2);
                break;
            //已入货(未付款)
            case 4:
                $query->where('pay_status', 0);
                $query->whereIn('in_storage_status', [1, 2]);
                break;
        }

        if (!empty($materielIdArr)) {
            $query->whereIn('a.id', $materielIdArr);
        } else {
            $query->orWhereIn('a.id', $materielIdArr);
        }

        $query = $query->orderBy('id', 'desc')
            ->paginate($data['pageSize'], ['*'], '', $data['currentPage'])->toArray();

        foreach ($query['data'] as &$value) {
            $value['out_order_no'] = empty($value['out_order_no']) ? '' : $value['out_order_no'];
            foreach ($value['materiel_content'] as $v) {
                @$value['total_num'] += $v['num'];
            }

            $value['customer_phone'] = '';
            if (!empty($value['supplier_customer_id'])) {
                $value['customer_phone'] = SupplierCustomerModel::query()
                    ->where('id', $value['supplier_customer_id'])->value('phone') ?? '';
            }
        }

        return $query;
    }

    static public function payHistory($id)
    {
        if (empty(MaterielPayHistoryModel::where('materiel_id', $id)->first())) {
            return '';
        } else {
            return MaterielPayHistoryModel::select(
                'a.purchase_no',
                'b.materiel_id',
                'b.money',
                'b.pay_time',
                'b.payer_account',
                'b.main_id',
                'b.created_at'
            )
                ->from('materiel as a')
                ->leftJoin('materiel_pay_history as b', 'a.id', '=', 'b.materiel_id')
                ->where('a.id', $id)
                ->get()->toArray();
        }
    }

    static public function createBatchInfo($batchNo, $storageManageId, $cost, $num, $materielId, $mainId, $data = [])
    {
        StorageBatchModel::insert([
            'batch_no' => $batchNo,
            'storage_manage_id' => $storageManageId,
            'batch_num' => $num,
            'batch_left_num' => $num,
            'batch_cost' => $cost,
            'materiel_id' => $materielId,
            'main_id' => $mainId,
            'created_at' => time(),
            'inspector' => !empty($data['inspector']) ? $data['inspector'] : "",
            'binding_supplier' => !empty($data['binding_supplier']) ? $data['binding_supplier'] : "",
            'expiration_date' => !empty($data['expiration_date']) ? $data['expiration_date'] : "",
            'warning_time' => !empty($data['warning_time']) ? $data['warning_time'] : "",
            'production_time' => !empty($data['production_time']) ? strtotime($data['production_time']) : "",
            'delivery_time' => !empty($data['delivery_time']) ? strtotime($data['delivery_time']) : "",
            'production_order_number' => !empty($data['production_order_number']) ? $data['production_order_number'] : "",
            'external_order_number' => !empty($data['external_order_number']) ? $data['external_order_number'] : "",
        ]);

        return true;
    }

    static public function createBatchInfoGetId($batchNo, $storageManageId, $cost, $num, $materielId, $mainId, $data = [])
    {
        return StorageBatchModel::insertGetId([
            'batch_no' => $batchNo,
            'storage_manage_id' => $storageManageId,
            'batch_num' => $num,
            'batch_left_num' => $num,
            'batch_cost' => $cost,
            'materiel_id' => $materielId,
            'main_id' => $mainId,
            'created_at' => time(),
            'inspector' => !empty($data['inspector']) ? $data['inspector'] : "",
            'binding_supplier' => !empty($data['binding_supplier']) ? $data['binding_supplier'] : "",
            'expiration_date' => !empty($data['expiration_date']) ? $data['expiration_date'] : "",
            'warning_time' => !empty($data['warning_time']) ? $data['warning_time'] : "",
            'production_time' => !empty($data['production_time']) ? strtotime($data['production_time']) : "",
            'delivery_time' => !empty($data['delivery_time']) ? strtotime($data['delivery_time']) : "",
            'production_order_number' => !empty($data['production_order_number']) ? $data['production_order_number'] : "",
            'external_order_number' => !empty($data['external_order_number']) ? $data['external_order_number'] : "",
        ]);
    }

    static public function cancel($mainId, $data)
    {
        $checkMaterielInfo = MaterielModel::where([
            'id' => $data['id'],
            'delete_flag' => 0
        ])->first();

        if (empty($checkMaterielInfo)) {
            return ['code' => 1, 'msg' => '该采购单不存在或已被删除', 'data' => ''];
        }

        if ($checkMaterielInfo['repeal_status']) {
            return ['code' => 1, 'msg' => '该采购单已撤销，无法重复操作', 'data' => ''];
        }

        $logInfo = LogInstorageModel::where([
            'all_id_type' => 3,
            'all_id' => $data['id'],
            'is_cancel' => 0
        ])->get()->toArray();

        DB::beginTransaction();
        try {
            if (!empty($logInfo)) {
                foreach ($logInfo as $value) {
                    $storageManageInfo = StorageManageModel::select(
                        'a.id',
                        'in_storage_num',
                        'b.materiel_name',
                        'b.type_name',
                        'type_id'
                    )
                        ->from('storage_manage as a')
                        ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                        ->where('a.id', $value['curr_storage_manage_id'])->first();
                    if (empty($storageManageInfo)) {
                        throw new \RuntimeException('库存信息不存在，无法撤销');
                    }

                    if ($storageManageInfo['delete_flag']) {
                        throw new \RuntimeException('商品：' . $storageManageInfo['materiel_name'] . '-' . $storageManageInfo['type_name'] . '已被删除，无法完成撤销');
                    }
                    if (!OperMainAccountModel::query()
                        ->where([
                            'main_id' => $mainId,
                            'delete_flag' => 0
                        ])->exists()) {
                        if ($storageManageInfo['in_storage_num'] < $value['operate_num']) {
                            throw new \RuntimeException('商品：' . $storageManageInfo['materiel_name'] . '-' . $storageManageInfo['type_name'] . '库存数不足(当前库存:' . $storageManageInfo['in_storage_num'] . ',操作数量:' . $value['operate_num'] . ')，无法完成撤销');
                        }
                    }
                    $bCond = [];
                    if (!empty($value['batch_id'])) {
                        $bCond['id'] = $value['batch_id'];
                    } elseif (!empty($value['batch_no'])) {
                        $bCond['batch_no'] = $value['batch_no'];
                    }
                    if (!empty($bCond)) {
                        $storageBatchInfo = StorageBatchModel::where($bCond)->first();
                        if (!empty($storageBatchInfo)) {
                            /* if ($value['operate_num'] > $storageBatchInfo['batch_left_num']) {
                                 throw new \RuntimeException('商品：' . $storageManageInfo['materiel_name'] . '-' . $storageManageInfo['type_name'] . '剩余批次数量不足，无法完成撤销');

                             }*/
                            //扣除批次数量
                            $storageBatchInfo->batch_left_num = 0;
                            $storageBatchInfo->save();
                        }
                    }
                    $materielTypeInfo = MaterielsTypeModel::where('id', $storageManageInfo['type_id'])->first();

                    $materielTypeInfo->cost = $materielTypeInfo['last_cost'];
                    $materielTypeInfo->save();


                    StorageManageModel::where('id', $value['curr_storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num - ' . $value['operate_num']),
                            //'virtual_storage_num' => DB::raw("virtual_storage_num - ".$value['operate_num']),
                            'materiel_mean_cost' => $materielTypeInfo['last_cost'],
                        ]);
                }

                $logInfoId = [];
                foreach ($logInfo as $val) {
                    $logInfoId[] = $val['id'];
                }

                LogInstorageModel::whereIn('id', $logInfoId)->update(['is_cancel' => 1]);
                $contentList = MaterielContentModel::query()
                    ->where('materiel_id', $data['id'])->get();
                if (!empty($contentList)) {
                    foreach ($contentList->toArray() as $mVal) {
                        $inSerialInfo = MaterielSerialNumberModel::query()
                            ->where([
                                'type_id' => $mVal['type_id'],
                                'materiel_content_id' => $mVal['id']
                            ])->get();
                        if (!empty($inSerialInfo)) {
                            foreach ($inSerialInfo as $iVal) {
                                $serialNumberModel = SerialNumberModel::query()
                                    ->where([
                                        'main_id' => $mainId,
                                        'goods_id' => $mVal['type_id'],
                                    ]);
                                if (strpos($iVal['serial_no'], ',') !== false) {
                                    $serialArr = explode(',', $iVal['serial_no']);
                                    $serialNumberModel->whereIn('serial_no', $serialArr);
                                } else {
                                    $serialNumberModel->where('serial_no', $iVal['serial_no']);
                                }
                                $serialNumberModel->update(['delete_flag' => 1]);
                                $iVal->delete();
                            }
                        }
                    }
                }
            }

            MaterielModel::where('id', $data['id'])->update(['repeal_status' => 1]);
            MaterielContentModel::where('materiel_id', $data['id'])->update(['repeal_status' => 1]);
            CheckModel::where([
                'type' => 3,
                'all_id' => $data['id']
            ])->update(['repeal_status' => 1]);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('采购撤销异常' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //重新下单
    static public function addAgain($userId, $parentId, $data)
    {
        $materielInfo = MaterielModel::where('id', $data['id'])->first()->toArray();
        $materielContentInfo = MaterielContentModel::where('materiel_id', $data['id'])->get()->toArray();

        unset($materielInfo['id']);
        $materielInfo['purchase_no'] = $data['purchase_no'];
        $materielInfo['repeal_status'] = 0;
        $materielInfo['user_id'] = $userId;
        $materielInfo['main_id'] = $parentId;
        $materielInfo['created_at'] = time();
        $materielInfo['updated_at'] = NULL;
        $materielInfo['remark'] = '';
        $materielInfo['pay_status'] = 0;
        $materielInfo['in_storage_status'] = 0;
        $materielInfo['purchase_time'] = time();
        $materielInfo['purchase_date'] = strtotime(date('Y-m-d', strtotime($materielInfo['purchase_time'])));

        DB::beginTransaction();

        try {
            $insertId = MaterielModel::insertGetId($materielInfo);

            foreach ($materielContentInfo as $k => $v) {
                unset($materielContentInfo[$k]['id']);
                unset($materielContentInfo[$k]['updated_at']);

                $materielContentInfo[$k]['materiel_id'] = $insertId;
                $materielContentInfo[$k]['rest_num'] = $v['num'];
                $materielContentInfo[$k]['user_id'] = $userId;
                $materielContentInfo[$k]['main_id'] = $parentId;
                $materielContentInfo[$k]['created_at'] = time();
            }

            CheckModel::insert([
                'type' => 3,
                'all_id' => $insertId,
                'main_id' => $parentId,
                'user_id' => $userId,
                'status' => 0,
                'out_in_status' => 0,
                'created_at' => time(),
                'order_no' => $data['purchase_no']
            ]);
            $materLogisticsList = MaterielLogisticsInfoModel::select(
                'main_id',
                'logistics_company',
                'logistics_order_no'
            )->where(
                'materiel_id', $data['id']
            )->get()->toArray();
            if (!empty($materLogisticsList)) {
                foreach ($materLogisticsList as &$lVal) {
                    $lVal['materiel_id'] = $insertId;
                    $lVal['user_id'] = $userId;
                    $lVal['created_at'] = time();
                }
                MaterielLogisticsInfoModel::insert($materLogisticsList);
            }

            MaterielContentModel::insert($materielContentInfo);
            DB::commit();
            return ['code' => 0, 'reg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('采购重新下单:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'reg' => $e->getMessage(), 'data' => ''];
        }
    }

    //删除指定采购
    static public function del($data)
    {
        $materielInfo = MaterielModel::where('id', $data['id'])->first();

        if ($materielInfo['pay_status'] == 1 || $materielInfo['in_storage_status'] == 1) {
            if ($materielInfo['repeal_status'] == 0) {
                return ['code' => 1, 'msg' => '无法删除，请检查此采购单状态', 'data' => ''];
            }
        } elseif ($materielInfo['pay_status'] == 0 && $materielInfo['in_storage_status'] == 2) {
            if ($materielInfo['repeal_status'] == 0) {
                return ['code' => 1, 'msg' => '无法删除，请检查此采购单状态', 'data' => ''];
            }
        }

        MaterielModel::where('id', $data['id'])->update(['delete_flag' => 1]);
        CheckModel::where('type', 3)->where('all_id', $data['id'])->update(['repeal_status' => 1]);
        $logData = '采购订单号：' . $materielInfo['purchase_no'] . '已删除！';
        CommonService::operateResult($data['user_id'], $data['logTime'], $data, $logData);
        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    //详细
    static public function detail($datas)
    {
        $data = MaterielModel::select(
            'a.*',
            'b.nickname',
            'b.username',
            'c.username as approver_name'
        )->from('materiel as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->leftJoin('admin as c', 'c.id', '=', 'a.approver_id')
            ->with('materielContent', function ($query) {
                $query->select(
                    'materiel_content.id',
                    'materiel_content.type_id',
                    'materiel_id',
                    'unit_price',
                    'num',
                    'materiel_content.rest_num',
                    'a.materiel_name',
                    'a.type_name',
                    'a.materiel_no',
                    'a.materiel_img',
                    'materiel_content.storage_id',
                    'b.storage_name',
                    'b.storage_address',
                    'a.is_use_serial',
                    'materiel_content.shelf_id',
                    'materiel_content.location_id',
                    's.shelf_name',
                    'l.location_name',
                    'materiel_content.remark',
                    'texture',
                    'executive_standard',
                    'materiel_unit',
                    'is_product_materiel'
                )
                    ->leftJoin('materiel_type as a', 'a.id', '=', 'materiel_content.type_id')
                    ->leftJoin('storage as b', 'b.id', '=', 'materiel_content.storage_id')
                    ->leftJoin('storage_shelf as s', 'materiel_content.shelf_id', '=', 's.id')
                    ->leftJoin('storage_shelf_location as l', 'materiel_content.location_id', '=', 'l.id');
            })
            ->with('materielLogisticsInfo', function ($query) {
                $query->select(
                    'id',
                    'materiel_id',
                    'logistics_company',
                    'logistics_order_no'
                )->where('delete_flag', 0);
            })
            ->where('a.id', $datas['id'])
            ->where('a.delete_flag', 0)
            ->orderBy('a.id', 'desc')
            ->first();
        $data = !empty($data) ? $data->toArray() : [];
        $totalNum = 0;
        $totalPrice = 0;
        if (!empty($data['materiel_content'])) {
            foreach ($data['materiel_content'] as &$val) {
                $val['in_num'] = $val['num'] - $val['rest_num'];
                $val['is_in'] = $val['num'] == $val['rest_num'] ? 0 : 1;
                $val['serial_number_list'] = [];
                if ($val['is_use_serial'] == 1) {
                    $snCondition['type_id'] = $val['type_id'];
                    $snCondition['materiel_content_id'] = $val['id'];
                    $list = MaterielSerialNumberModel::select('serial_no')
                        ->where($snCondition)->get()->toArray();
                    if (!empty($list)) {
                        $val['serial_number_list'] = array_column($list, 'serial_no');
                    }
                }
                $val['one_subtotal'] = $val['num'] * $val['unit_price'];
                $totalNum += $val['num'];
                $totalPrice += $val['num'] * $val['unit_price'];
                $batchNo = LogInStorageModel::query()->where([
                    'all_id_type' => 3,
                    'all_id' => $val['materiel_id'],
                    'materiel_type_id' => $val['type_id']
                ])->value('batch_no');
                $val['batch_list'] = !empty($batchNo) ? $batchNo : '';
            }
        }

        if (!empty($data['materiel_logistics_info'])) {
            foreach ($data['materiel_logistics_info'] as &$val) {
                $val['logistics_order_no'] = !empty($val['logistics_order_no']) ?
                    explode(',', $val['logistics_order_no']) : [];

            }
        } else {
            $data['materiel_logistics_info'] = [];
        }
        if (!empty($data['logistics_company']) || !empty($data['logistics_order_no'])) {
            $data['materiel_logistics_info'][count($data['materiel_logistics_info'])] = [
                'logistics_company' => $data['logistics_company'] ?? "",
                'logistics_order_no' => [$data['logistics_order_no']] ?? []
            ];
        }
        $data['check_info'] = CheckModel::select(
            'id',
            'type',
            'all_id',
            'status',
            'eudit_status',
            'order_no'
        )->where([
            'all_id' => $data['id'],
            'type' => 3,
            'repeal_status' => 0
        ])->first() ?? [];
        $data['total_num'] = $totalNum;
        $data['total_price'] = $totalPrice;
        $adminInfo = AdminModel::query()->select()
            ->where([
                'id' => $data['main_id']
            ])->first();
        $data['company_name'] = $adminInfo['company_name'] ?? '';
        $data['company_logo_img'] = $adminInfo['company_logo_img'] ?? '';
        $data['company_address'] = $adminInfo['company_address'] ?? '';
        return $data;
    }

    //详细
    static public function newMaterielDetail($datas)
    {
        $data = MaterielModel::select(
            'a.*',
            'b.nickname',
            'b.username',
            'c.username as approver_name'
        )->from('materiel as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->leftJoin('admin as c', 'c.id', '=', 'a.approver_id')
            ->with('materielContent', function ($query) {
                $query->select(
                    'materiel_content.id',
                    'materiel_content.type_id',
                    'materiel_id',
                    'unit_price',
                    'num',
                    'materiel_content.rest_num',
                    'a.materiel_name',
                    'a.type_name',
                    'a.materiel_no',
                    'a.materiel_img',
                    'materiel_content.storage_id',
                    'b.storage_name',
                    'b.storage_address',
                    'a.is_use_serial',
                    'materiel_content.shelf_id',
                    'materiel_content.location_id',
                    's.shelf_name',
                    'l.location_name',
                    'materiel_content.remark',
                    'texture',
                    'executive_standard',
                    'materiel_unit',
                    'is_product_materiel',
                    'a.bar_code',
                    'a.inventory_code',
                    'a.materiel_class_id'
                )
                    ->leftJoin('materiel_type as a', 'a.id', '=', 'materiel_content.type_id')
                    ->leftJoin('storage as b', 'b.id', '=', 'materiel_content.storage_id')
                    ->leftJoin('storage_shelf as s', 'materiel_content.shelf_id', '=', 's.id')
                    ->leftJoin('storage_shelf_location as l', 'materiel_content.location_id', '=', 'l.id');
            })
            ->with('materielLogisticsInfo', function ($query) {
                $query->select(
                    'id',
                    'materiel_id',
                    'logistics_company',
                    'logistics_order_no'
                )->where('delete_flag', 0);
            })
            ->where('a.id', $datas['id'])
            ->where('a.delete_flag', 0)
            ->orderBy('a.id', 'desc')
            ->first();
        $data = !empty($data) ? $data->toArray() : [];
        $totalNum = 0;
        $totalPrice = 0;
        $goodsData = [];
        if (!empty($data['materiel_content'])) {
            foreach ($data['materiel_content'] as &$val) {
                $goodsData[] = [
                    'materiel_name' => $val['materiel_name'],
                    'materiel_img' => $val['materiel_img'],
                ];
                $val['in_num'] = $val['num'] - $val['rest_num'];
                $val['is_in'] = $val['num'] == $val['rest_num'] ? 0 : 1;
                $val['serial_number_list'] = [];
                if ($val['is_use_serial'] == 1) {
                    $snCondition['type_id'] = $val['type_id'];
                    $snCondition['materiel_content_id'] = $val['id'];
                    $list = MaterielSerialNumberModel::select('serial_no')
                        ->where($snCondition)->get()->toArray();
                    if (!empty($list)) {
                        $val['serial_number_list'] = array_column($list, 'serial_no');
                    }
                }
                $val['one_subtotal'] = $val['num'] * $val['unit_price'];
                $totalNum += $val['num'];
                $totalPrice += $val['num'] * $val['unit_price'];
                $batchNo = LogInStorageModel::query()->where([
                    'all_id_type' => 3,
                    'all_id' => $val['materiel_id'],
                    'materiel_type_id' => $val['type_id']
                ])->value('batch_no');
                $val['batch_list'] = !empty($batchNo) ? $batchNo : '';
            }

            $goodsArr = array_map("unserialize", array_unique(array_map("serialize", $goodsData)));

            foreach ($goodsArr as &$gVal) {
                $totalGoodsNum = 0;
                $totalGoodsPrice = 0;
                foreach ($data['materiel_content'] as $lVal) {
                    $sClassInfo = MaterielClassModel::query()
                        ->where('id', $lVal['materiel_class_id'])->first();
                    $fClassInfo = [];
                    if (isset($sClassInfo['parent_id'])) {
                        $fClassInfo = MaterielClassModel::query()
                            ->where('id', $sClassInfo['parent_id'])->first();
                    }
                    $lVal['s_class_id'] = $sClassInfo['id'] ?? '';
                    $lVal['s_class_name'] = $sClassInfo['class_name'] ?? '';
                    $lVal['f_class_id'] = $fClassInfo['id'] ?? '';
                    $lVal['f_class_name'] = $fClassInfo['class_name'] ?? '';
                    if ($gVal['materiel_name'] === $lVal['materiel_name']) {
                        $gVal['goods_list'][] = $lVal;
                        $totalGoodsNum += $lVal['num'];
                        $totalGoodsPrice += $lVal['num'] * $lVal['unit_price'];
                    }
                }
                $gVal['total_goods_num'] = $totalGoodsNum;
                $gVal['total_goods_price'] = $totalGoodsPrice;
            }

            $data['materiel_content'] = $goodsArr;
        }

        if (!empty($data['materiel_logistics_info'])) {
            foreach ($data['materiel_logistics_info'] as &$val) {
                $val['logistics_order_no'] = !empty($val['logistics_order_no']) ?
                    explode(',', $val['logistics_order_no']) : [];

            }
        } else {
            $data['materiel_logistics_info'] = [];
        }
        if (!empty($data['logistics_company']) || !empty($data['logistics_order_no'])) {
            $data['materiel_logistics_info'][count($data['materiel_logistics_info'])] = [
                'logistics_company' => $data['logistics_company'] ?? "",
                'logistics_order_no' => [$data['logistics_order_no']] ?? []
            ];
        }
        $data['check_info'] = CheckModel::select(
            'id',
            'type',
            'all_id',
            'status',
            'eudit_status',
            'order_no'
        )->where([
            'all_id' => $data['id'],
            'type' => 3,
            'repeal_status' => 0
        ])->first() ?? [];
        $data['total_num'] = $totalNum;
        $data['total_price'] = $totalPrice;
        $adminInfo = AdminModel::query()->select()
            ->where([
                'id' => $data['main_id']
            ])->first();
        $data['company_name'] = $adminInfo['company_name'] ?? '';
        $data['company_logo_img'] = $adminInfo['company_logo_img'] ?? '';
        $data['company_address'] = $adminInfo['company_address'] ?? '';
        return $data;
    }

    //添加采购但其他费用
    static public function addCharges($data)
    {
        //开启事务
        DB::beginTransaction();
        try {

            MaterielOtherChargesModel::insert($data);
            $model = MaterielModel::where('id', $data['materiel_id'])->first();
            //$model->final_money += $data['money'];
            $model->other_charges = $model->other_charges + $data['money'];
            $model->save();

            $logData = '采购单号 ：' . $model['purchase_no'] . '添加其他费用为' . $data['money'] . '元';
            DB::commit();//提交事务
            return ['code' => 0, 'msg' => 'success', 'data' => $logData];
        } catch (Exception $e) {
            DB::rollBack();//事务回滚
            //异常响应
            Log::debug('添加其他费用:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //编辑其他费用
    static public function editCharges($data)
    {
        //开启事务
        DB::beginTransaction();
        try {
            $beforeModel = MaterielOtherChargesModel::where('id', $data['id'])->first();
            MaterielOtherChargesModel::where('id', $data['id'])->update($data);
            $beforeMoney = $beforeModel['money'];
            $final = $data['money'] - $beforeMoney;
            $model = MaterielModel::where('id', $beforeModel['materiel_id'])->first();
            $model->final_money += $final;
            $model->other_charges = $model->other_charges + $final;
            $model->save();
            $logData = '采购单号 ：' . $model['purchase_no'] . '修改其他费用为' . $data['money'] . '元';
            DB::commit();//提交事务
            return ['code' => 0, 'msg' => 'success', 'data' => $logData];
        } catch (Exception $e) {
            DB::rollBack();//事务回滚
            //异常响应
            Log::debug('编辑其他费用:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //付款
    static public function payMaterielMoney($data)
    {
        unset($data['status']);
        $materielInfo = MaterielModel::where('id', $data['materiel_id'])->first();//销售单信息
        if (strtotime($materielInfo['created_at']) > '1713506400') {//2024年4月19日 14点之前的订单不需要审核
            $checkInfo = CheckModel::where([
                'all_id' => $materielInfo['id'],
                'type' => 3,
                'repeal_status' => 0
            ])->first();
            if (!empty($checkInfo)) {
                if (empty($checkInfo['eudit_status'])) {
                    return ['code' => 1, 'msg' => '采购单在待审批中！', 'data' => ''];
                }
                if ($checkInfo['eudit_status'] == 2) {
                    return ['code' => 1, 'msg' => '采购单未审批通过！', 'data' => ''];
                }
            }
        }
        $paidMomey = MaterielPayHistoryModel::where('materiel_id', $data['materiel_id'])->sum('money');//已收款金额

        $payInfo = MaterielPayHistoryModel::where('materiel_id', $data['materiel_id'])->first();

        if ($materielInfo['pay_status'] == 2) {
            return ['code' => 1, 'msg' => '支付已完成，无需重复支付', 'data' => ''];
        }

        //支付后实付金额
        $afterPayMoney = sprintf('%.6f', ($paidMomey + $data['money']));

        if ($afterPayMoney > $materielInfo['final_money']) {
            return ['code' => 1, 'msg' => '超出实际应付金额，请重试', 'data' => ''];
        }

        $payStatus = 1;
        if ($afterPayMoney == $materielInfo['final_money']) {
            $payStatus = 2;
        }

        DB::beginTransaction();

        try {
            if (empty($payInfo)) {
                MaterielModel::where('id', $data['materiel_id'])
                    ->update([
                        'fact_money' => 0
                    ]);
            }

            $tallyContent = TallyClassModel::where([
                'name' => '采购',
                'main_id' => $data['main_id']
            ])->first();
            TallyModel::insert([
                'tally_class_id' => $tallyContent['id'] ?? 0,
                'tally_class_name' => $tallyContent['name'] ?? '采购',
                'type' => 1,
                'money' => $data['money'],
                'order_no' => $materielInfo['purchase_no'],
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'add_time' => strtotime($materielInfo['purchase_time']),
                'created_at' => time()
            ]);
            unset($data['user_id']);
            MaterielModel::where('id', $data['materiel_id'])->increment('fact_money', $data['money'], [
                'pay_status' => $payStatus
            ]);
            $data['purchase_no'] = $materielInfo['purchase_no'];
            $data['pay_type'] = !empty($data['pay_type']) ? $data['pay_type'] : 0;
            MaterielPayHistoryModel::insert($data);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('采购付款异常:' . $e->getMessage());
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    public static function getSyncPrice($data)
    {
        return MaterielModel::getSyncPrice($data);
    }

    public static function getMaterielInfo($condition,$date)
    {
        $res1 = MaterielModel::query()->select(
            DB::raw('SUM(fact_money) as total_real_money'),
            DB::raw('SUM(final_money+other_charges-fact_money) as total_debt_money'),
            DB::raw('SUM(final_money) as total_final_money'),
            DB::raw('SUM(other_charges) as total_other_money'),
            DB::raw('count(*) as total_count'),
        )->where([
            'delete_flag' => 0,
            'repeal_status' => 0,
        ])->where($condition)
            ->whereBetween('created_at', [$date[0], $date[1]])->first();
        $materielIdArr = MaterielModel::query()->where([
            'delete_flag' => 0,
            'repeal_status' => 0,
        ])->where($condition)
            ->whereBetween('created_at', [$date[0], $date[1]])
            ->pluck('id')->toArray();
        $res3 = [];
        if (!empty($materielIdArr)) {
            $res3 = MaterielContentModel::query()
                ->select(
                    DB::raw('SUM(num-rest_num) as total_residue_num'),
                    DB::raw('SUM(num) as total_num'),
                    DB::raw('SUM(rest_num) as total_out_num'),
                )->where([
                    'repeal_status' => 0,
                ])->where($condition)
                ->whereIn('materiel_id', $materielIdArr)
                ->first();
        }


        return [
            'm_total_real_money' => empty($res1['total_real_money']) ? 0 : sprintf('%.6f', $res1['total_real_money']),
            'm_total_rest_num' => empty($res3['total_out_num']) ? 0 : sprintf('%.6f', $res3['total_out_num']),
            'm_total_residue_num' => empty($res3['total_residue_num']) ? 0 : sprintf('%.6f', $res3['total_residue_num']),
            'm_total_debt_money' => empty($res1['total_debt_money']) ? 0 : sprintf('%.6f', $res1['total_debt_money']),
            'm_total_order_count' => empty($res1['total_count']) ? 0 : sprintf('%.6f', $res1['total_count']),
            'm_total_sell_goods_num' => empty($res3['total_num']) ? 0 : sprintf('%.6f', $res3['total_num']),
            'm_total_final_money' => empty($res1['total_final_money']) ? 0 : sprintf('%.6f', $res1['total_final_money']),
            'm_total_other_money' => empty($res1['total_other_money']) ? 0 : sprintf('%.6f', $res1['total_other_money']),
        ];
    }
}
